--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -59,16 +59,20 @@ add_makefiles "
Makefile
config/autoconf.mk
"
if [ "$MOZ_LDAP_XPCOM" ]; then
. "${srcdir}/directory/makefiles.sh"
fi
+if [ "$MOZ_COMPOSER" ]; then
+ . "${srcdir}/editor/ui/makefiles.sh"
+fi
+
if [ "$MOZ_MAIL_NEWS" ]; then
. "${srcdir}/mailnews/makefiles.sh"
fi
if [ "$MOZ_CALENDAR" ]; then
. "${srcdir}/calendar/shared_makefiles.sh"
. "${srcdir}/calendar/lightning/makefiles.sh"
fi
new file mode 100644
--- /dev/null
+++ b/editor/ui/Makefile.in
@@ -0,0 +1,54 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Brian Ryner <bryner@brianryner.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = \
+ locales \
+ $(NULL)
+
+ifndef MOZ_STANDALONE_COMPOSER
+PREF_JS_EXPORTS = $(srcdir)/composer.js
+EXTRA_COMPONENTS = nsComposerCmdLineHandler.js
+endif
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer.js
@@ -0,0 +1,138 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Benjamin Smedberg <bsmedberg@covad.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Default preferences for seamonkey composer. This file
+ * was copied from mozilla/modules/libpref/src/init/editor.js
+ *
+ * If you're looking for the default prefs of standalone
+ * composer, see mozilla/composer/app/profile/all.js
+ */
+
+pref("editor.author", "");
+
+pref("editor.text_color", "#000000");
+pref("editor.link_color", "#0000FF");
+pref("editor.active_link_color", "#000088");
+pref("editor.followed_link_color", "#FF0000");
+pref("editor.background_color", "#FFFFFF");
+pref("editor.use_background_image", false);
+pref("editor.default_background_image", "");
+pref("editor.use_custom_default_colors", 1);
+
+pref("editor.hrule.height", 2);
+pref("editor.hrule.width", 100);
+pref("editor.hrule.width_percent", true);
+pref("editor.hrule.shading", true);
+pref("editor.hrule.align", 1); // center
+
+pref("editor.table.maintain_structure", true);
+
+pref("editor.prettyprint", true);
+
+pref("editor.throbber.url","chrome://editor-region/locale/region.properties");
+
+pref("editor.toolbars.showbutton.new", true);
+pref("editor.toolbars.showbutton.open", true);
+pref("editor.toolbars.showbutton.save", true);
+pref("editor.toolbars.showbutton.publish", true);
+pref("editor.toolbars.showbutton.preview", true);
+pref("editor.toolbars.showbutton.cut", false);
+pref("editor.toolbars.showbutton.copy", false);
+pref("editor.toolbars.showbutton.paste", false);
+pref("editor.toolbars.showbutton.print", true);
+pref("editor.toolbars.showbutton.find", false);
+pref("editor.toolbars.showbutton.image", true);
+pref("editor.toolbars.showbutton.hline", false);
+pref("editor.toolbars.showbutton.table", true);
+pref("editor.toolbars.showbutton.link", true);
+pref("editor.toolbars.showbutton.namedAnchor", false);
+
+pref("editor.toolbars.showbutton.bold", true);
+pref("editor.toolbars.showbutton.italic", true);
+pref("editor.toolbars.showbutton.underline", true);
+pref("editor.toolbars.showbutton.DecreaseFontSize", true);
+pref("editor.toolbars.showbutton.IncreaseFontSize", true);
+pref("editor.toolbars.showbutton.ul", true);
+pref("editor.toolbars.showbutton.ol", true);
+pref("editor.toolbars.showbutton.outdent", true);
+pref("editor.toolbars.showbutton.indent", true);
+
+pref("editor.toolbars.showbutton.absolutePosition", true);
+pref("editor.toolbars.showbutton.decreaseZIndex", true);
+pref("editor.toolbars.showbutton.increaseZIndex", true);
+
+pref("editor.history.url_maximum", 10);
+
+pref("editor.publish.", "");
+pref("editor.lastFileLocation.image", "");
+pref("editor.lastFileLocation.html", "");
+pref("editor.save_associated_files", true);
+pref("editor.always_show_publish_dialog", false);
+
+/*
+ * What are the entities that you want Mozilla to save using mnemonic
+ * names rather than numeric codes? E.g. If set, we'll output
+ * otherwise, we may output 0xa0 depending on the charset.
+ *
+ * "none" : don't use any entity names; only use numeric codes.
+ * "basic" : use entity names just for & < > " for
+ * interoperability/exchange with products that don't support more
+ * than that.
+ * "latin1" : use entity names for 8bit accented letters and other special
+ * symbols between 128 and 255.
+ * "html" : use entity names for 8bit accented letters, greek letters, and
+ * other special markup symbols as defined in HTML4.
+ */
+//pref("editor.encode_entity", "html");
+
+#ifndef XP_MACOSX
+#ifdef XP_UNIX
+pref("editor.disable_spell_checker", false);
+pref("editor.dont_lock_spell_files", true);
+#endif
+#endif
+
+pref("editor.CR_creates_new_p", false);
+
+// Pasting images from the clipboard, order of encoding preference:
+// JPEG-PNG-GIF=0, PNG-JPEG-GIF=1, GIF-JPEG-PNG=2
+pref("clipboard.paste_image_type", 1);
+#ifdef XP_WIN
+pref("clipboard.paste_image_quality", 92); // for JPEG on Windows only
+#endif
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/ComposerCommands.js
@@ -0,0 +1,3956 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Simon Fraser (sfraser@netscape.com)
+ * Ryan Cassin (rcassin@supernova.org)
+ * Kathleen Brade (brade@netscape.com)
+ * Daniel Glazman (glazman@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementations of nsIControllerCommand for composer commands */
+
+var gComposerJSCommandControllerID = 0;
+
+
+//-----------------------------------------------------------------------------------
+function SetupHTMLEditorCommands()
+{
+ var commandTable = GetComposerCommandTable();
+ if (!commandTable)
+ return;
+
+ // Include everthing a text editor does
+ SetupTextEditorCommands();
+
+ //dump("Registering HTML editor commands\n");
+
+ commandTable.registerCommand("cmd_renderedHTMLEnabler", nsDummyHTMLCommand);
+
+ commandTable.registerCommand("cmd_grid", nsGridCommand);
+
+ commandTable.registerCommand("cmd_listProperties", nsListPropertiesCommand);
+ commandTable.registerCommand("cmd_pageProperties", nsPagePropertiesCommand);
+ commandTable.registerCommand("cmd_colorProperties", nsColorPropertiesCommand);
+ commandTable.registerCommand("cmd_advancedProperties", nsAdvancedPropertiesCommand);
+ commandTable.registerCommand("cmd_objectProperties", nsObjectPropertiesCommand);
+ commandTable.registerCommand("cmd_removeNamedAnchors", nsRemoveNamedAnchorsCommand);
+ commandTable.registerCommand("cmd_editLink", nsEditLinkCommand);
+
+ commandTable.registerCommand("cmd_form", nsFormCommand);
+ commandTable.registerCommand("cmd_inputtag", nsInputTagCommand);
+ commandTable.registerCommand("cmd_inputimage", nsInputImageCommand);
+ commandTable.registerCommand("cmd_textarea", nsTextAreaCommand);
+ commandTable.registerCommand("cmd_select", nsSelectCommand);
+ commandTable.registerCommand("cmd_button", nsButtonCommand);
+ commandTable.registerCommand("cmd_label", nsLabelCommand);
+ commandTable.registerCommand("cmd_fieldset", nsFieldSetCommand);
+ commandTable.registerCommand("cmd_isindex", nsIsIndexCommand);
+ commandTable.registerCommand("cmd_image", nsImageCommand);
+ commandTable.registerCommand("cmd_hline", nsHLineCommand);
+ commandTable.registerCommand("cmd_link", nsLinkCommand);
+ commandTable.registerCommand("cmd_anchor", nsAnchorCommand);
+ commandTable.registerCommand("cmd_insertHTMLWithDialog", nsInsertHTMLWithDialogCommand);
+ commandTable.registerCommand("cmd_insertBreak", nsInsertBreakCommand);
+ commandTable.registerCommand("cmd_insertBreakAll",nsInsertBreakAllCommand);
+
+ commandTable.registerCommand("cmd_table", nsInsertOrEditTableCommand);
+ commandTable.registerCommand("cmd_editTable", nsEditTableCommand);
+ commandTable.registerCommand("cmd_SelectTable", nsSelectTableCommand);
+ commandTable.registerCommand("cmd_SelectRow", nsSelectTableRowCommand);
+ commandTable.registerCommand("cmd_SelectColumn", nsSelectTableColumnCommand);
+ commandTable.registerCommand("cmd_SelectCell", nsSelectTableCellCommand);
+ commandTable.registerCommand("cmd_SelectAllCells", nsSelectAllTableCellsCommand);
+ commandTable.registerCommand("cmd_InsertTable", nsInsertTableCommand);
+ commandTable.registerCommand("cmd_InsertRowAbove", nsInsertTableRowAboveCommand);
+ commandTable.registerCommand("cmd_InsertRowBelow", nsInsertTableRowBelowCommand);
+ commandTable.registerCommand("cmd_InsertColumnBefore", nsInsertTableColumnBeforeCommand);
+ commandTable.registerCommand("cmd_InsertColumnAfter", nsInsertTableColumnAfterCommand);
+ commandTable.registerCommand("cmd_InsertCellBefore", nsInsertTableCellBeforeCommand);
+ commandTable.registerCommand("cmd_InsertCellAfter", nsInsertTableCellAfterCommand);
+ commandTable.registerCommand("cmd_DeleteTable", nsDeleteTableCommand);
+ commandTable.registerCommand("cmd_DeleteRow", nsDeleteTableRowCommand);
+ commandTable.registerCommand("cmd_DeleteColumn", nsDeleteTableColumnCommand);
+ commandTable.registerCommand("cmd_DeleteCell", nsDeleteTableCellCommand);
+ commandTable.registerCommand("cmd_DeleteCellContents", nsDeleteTableCellContentsCommand);
+ commandTable.registerCommand("cmd_JoinTableCells", nsJoinTableCellsCommand);
+ commandTable.registerCommand("cmd_SplitTableCell", nsSplitTableCellCommand);
+ commandTable.registerCommand("cmd_TableOrCellColor", nsTableOrCellColorCommand);
+ commandTable.registerCommand("cmd_NormalizeTable", nsNormalizeTableCommand);
+ commandTable.registerCommand("cmd_smiley", nsSetSmiley);
+ commandTable.registerCommand("cmd_ConvertToTable", nsConvertToTable);
+}
+
+function SetupTextEditorCommands()
+{
+ var commandTable = GetComposerCommandTable();
+ if (!commandTable)
+ return;
+
+ //dump("Registering plain text editor commands\n");
+
+ commandTable.registerCommand("cmd_find", nsFindCommand);
+ commandTable.registerCommand("cmd_findNext", nsFindAgainCommand);
+ commandTable.registerCommand("cmd_findPrev", nsFindAgainCommand);
+ commandTable.registerCommand("cmd_rewrap", nsRewrapCommand);
+ commandTable.registerCommand("cmd_spelling", nsSpellingCommand);
+ commandTable.registerCommand("cmd_validate", nsValidateCommand);
+ commandTable.registerCommand("cmd_checkLinks", nsCheckLinksCommand);
+ commandTable.registerCommand("cmd_insertChars", nsInsertCharsCommand);
+}
+
+function SetupComposerWindowCommands()
+{
+ // Don't need to do this if already done
+ if (gComposerWindowControllerID)
+ return;
+
+ // Create a command controller and register commands
+ // specific to Web Composer window (file-related commands, HTML Source...)
+ // We can't use the composer controller created on the content window else
+ // we can't process commands when in HTMLSource editor
+ // IMPORTANT: For each of these commands, the doCommand method
+ // must first call FinishHTMLSource()
+ // to go from HTML Source mode to any other edit mode
+
+ var windowControllers = window.controllers;
+
+ if (!windowControllers) return;
+
+ var commandTable;
+ var composerController;
+ var editorController;
+ try {
+ composerController = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
+
+ editorController = composerController.QueryInterface(Components.interfaces.nsIControllerContext);
+ editorController.init(null); // init it without passing in a command table
+
+ // Get the nsIControllerCommandTable interface we need to register commands
+ var interfaceRequestor = composerController.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+ commandTable = interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
+ }
+ catch (e)
+ {
+ dump("Failed to create composerController\n");
+ return;
+ }
+
+
+ if (!commandTable)
+ {
+ dump("Failed to get interface for nsIControllerCommandManager\n");
+ return;
+ }
+
+ // File-related commands
+ commandTable.registerCommand("cmd_open", nsOpenCommand);
+ commandTable.registerCommand("cmd_save", nsSaveCommand);
+ commandTable.registerCommand("cmd_saveAs", nsSaveAsCommand);
+ commandTable.registerCommand("cmd_exportToText", nsExportToTextCommand);
+ commandTable.registerCommand("cmd_saveAndChangeEncoding", nsSaveAndChangeEncodingCommand);
+ commandTable.registerCommand("cmd_publish", nsPublishCommand);
+ commandTable.registerCommand("cmd_publishAs", nsPublishAsCommand);
+ commandTable.registerCommand("cmd_publishSettings",nsPublishSettingsCommand);
+ commandTable.registerCommand("cmd_revert", nsRevertCommand);
+ commandTable.registerCommand("cmd_openRemote", nsOpenRemoteCommand);
+ commandTable.registerCommand("cmd_preview", nsPreviewCommand);
+ commandTable.registerCommand("cmd_editSendPage", nsSendPageCommand);
+ commandTable.registerCommand("cmd_print", nsPrintCommand);
+ commandTable.registerCommand("cmd_printSetup", nsPrintSetupCommand);
+ commandTable.registerCommand("cmd_quit", nsQuitCommand);
+ commandTable.registerCommand("cmd_close", nsCloseCommand);
+ commandTable.registerCommand("cmd_preferences", nsPreferencesCommand);
+
+ // Edit Mode commands
+ if (GetCurrentEditorType() == "html")
+ {
+ commandTable.registerCommand("cmd_NormalMode", nsNormalModeCommand);
+ commandTable.registerCommand("cmd_AllTagsMode", nsAllTagsModeCommand);
+ commandTable.registerCommand("cmd_HTMLSourceMode", nsHTMLSourceModeCommand);
+ commandTable.registerCommand("cmd_PreviewMode", nsPreviewModeCommand);
+ commandTable.registerCommand("cmd_FinishHTMLSource", nsFinishHTMLSource);
+ commandTable.registerCommand("cmd_CancelHTMLSource", nsCancelHTMLSource);
+ commandTable.registerCommand("cmd_updateStructToolbar", nsUpdateStructToolbarCommand);
+ }
+
+ windowControllers.insertControllerAt(0, editorController);
+
+ // Store the controller ID so we can be sure to get the right one later
+ gComposerWindowControllerID = windowControllers.getControllerId(editorController);
+}
+
+//-----------------------------------------------------------------------------------
+function GetComposerCommandTable()
+{
+ var controller;
+ if (gComposerJSCommandControllerID)
+ {
+ try {
+ controller = window.content.controllers.getControllerById(gComposerJSCommandControllerID);
+ } catch (e) {}
+ }
+ if (!controller)
+ {
+ //create it
+ controller = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
+
+ var editorController = controller.QueryInterface(Components.interfaces.nsIControllerContext);
+ editorController.init(null);
+ editorController.setCommandContext(GetCurrentEditorElement());
+ window.content.controllers.insertControllerAt(0, controller);
+
+ // Store the controller ID so we can be sure to get the right one later
+ gComposerJSCommandControllerID = window.content.controllers.getControllerId(controller);
+ }
+
+ if (controller)
+ {
+ var interfaceRequestor = controller.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+ return interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
+ }
+ return null;
+}
+
+//-----------------------------------------------------------------------------------
+function goUpdateCommandState(command)
+{
+ try
+ {
+ var controller = top.document.commandDispatcher.getControllerForCommand(command);
+ if (!(controller instanceof Components.interfaces.nsICommandController))
+ return;
+
+ var params = newCommandParams();
+ if (!params) return;
+
+ controller.getCommandStateWithParams(command, params);
+
+ switch (command)
+ {
+ case "cmd_bold":
+ case "cmd_italic":
+ case "cmd_underline":
+ case "cmd_var":
+ case "cmd_samp":
+ case "cmd_code":
+ case "cmd_acronym":
+ case "cmd_abbr":
+ case "cmd_cite":
+ case "cmd_strong":
+ case "cmd_em":
+ case "cmd_superscript":
+ case "cmd_subscript":
+ case "cmd_strikethrough":
+ case "cmd_tt":
+ case "cmd_nobreak":
+ case "cmd_ul":
+ case "cmd_ol":
+ pokeStyleUI(command, params.getBooleanValue("state_all"));
+ break;
+
+ case "cmd_paragraphState":
+ case "cmd_align":
+ case "cmd_highlight":
+ case "cmd_backgroundColor":
+ case "cmd_fontColor":
+ case "cmd_fontFace":
+ case "cmd_fontSize":
+ case "cmd_absPos":
+ pokeMultiStateUI(command, params);
+ break;
+
+ case "cmd_decreaseZIndex":
+ case "cmd_increaseZIndex":
+ case "cmd_indent":
+ case "cmd_outdent":
+ case "cmd_increaseFont":
+ case "cmd_decreaseFont":
+ case "cmd_removeStyles":
+ case "cmd_smiley":
+ break;
+
+ default: dump("no update for command: " +command+"\n");
+ }
+ }
+ catch (e) { dump("An error occurred updating the "+command+" command: \n"+e+"\n"); }
+}
+
+function goUpdateComposerMenuItems(commandset)
+{
+ //dump("Updating commands for " + commandset.id + "\n");
+
+ for (var i = 0; i < commandset.childNodes.length; i++)
+ {
+ var commandNode = commandset.childNodes[i];
+ var commandID = commandNode.id;
+ if (commandID)
+ {
+ goUpdateCommand(commandID); // enable or disable
+ if (commandNode.hasAttribute("state"))
+ goUpdateCommandState(commandID);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+function goDoCommandParams(command, params)
+{
+ try
+ {
+ var controller = top.document.commandDispatcher.getControllerForCommand(command);
+ if (controller && controller.isCommandEnabled(command))
+ {
+ if (controller instanceof Components.interfaces.nsICommandController)
+ {
+ controller.doCommandWithParams(command, params);
+
+ // the following two lines should be removed when we implement observers
+ if (params)
+ controller.getCommandStateWithParams(command, params);
+ }
+ else
+ {
+ controller.doCommand(command);
+ }
+ ResetStructToolbar();
+ }
+ }
+ catch (e)
+ {
+ dump("An error occurred executing the "+command+" command\n");
+ }
+}
+
+function pokeStyleUI(uiID, aDesiredState)
+{
+ try {
+ var commandNode = top.document.getElementById(uiID);
+ if (!commandNode)
+ return;
+
+ var uiState = ("true" == commandNode.getAttribute("state"));
+ if (aDesiredState != uiState)
+ {
+ var newState;
+ if (aDesiredState)
+ newState = "true";
+ else
+ newState = "false";
+ commandNode.setAttribute("state", newState);
+ }
+ } catch(e) { dump("poking UI for "+uiID+" failed: "+e+"\n"); }
+}
+
+function doStyleUICommand(cmdStr)
+{
+ try
+ {
+ var cmdParams = newCommandParams();
+ goDoCommandParams(cmdStr, cmdParams);
+ if (cmdParams)
+ pokeStyleUI(cmdStr, cmdParams.getBooleanValue("state_all"));
+
+ ResetStructToolbar();
+ } catch(e) {}
+}
+
+function pokeMultiStateUI(uiID, cmdParams)
+{
+ try
+ {
+ var commandNode = document.getElementById(uiID);
+ if (!commandNode)
+ return;
+
+ var isMixed = cmdParams.getBooleanValue("state_mixed");
+ var desiredAttrib;
+ if (isMixed)
+ desiredAttrib = "mixed";
+ else {
+ var valuetype = cmdParams.getValueType("state_attribute");
+ if (valuetype == Components.interfaces.nsICommandParams.eStringType) {
+ desiredAttrib = cmdParams.getCStringValue("state_attribute");
+ } else {
+ desiredAttrib = cmdParams.getStringValue("state_attribute");
+ }
+
+ }
+
+ var uiState = commandNode.getAttribute("state");
+ if (desiredAttrib != uiState)
+ {
+ commandNode.setAttribute("state", desiredAttrib);
+ }
+ } catch(e) {}
+}
+
+function doStatefulCommand(commandID, newState)
+{
+ var commandNode = document.getElementById(commandID);
+ if (commandNode)
+ commandNode.setAttribute("state", newState);
+ gContentWindow.focus(); // needed for command dispatch to work
+
+ try
+ {
+ var cmdParams = newCommandParams();
+ if (!cmdParams) return;
+
+ cmdParams.setStringValue("state_attribute", newState);
+ goDoCommandParams(commandID, cmdParams);
+
+ pokeMultiStateUI(commandID, cmdParams);
+
+ ResetStructToolbar();
+ } catch(e) { dump("error thrown in doStatefulCommand: "+e+"\n"); }
+}
+
+//-----------------------------------------------------------------------------------
+function PrintObject(obj)
+{
+ dump("-----" + obj + "------\n");
+ var names = "";
+ for (var i in obj)
+ {
+ if (i == "value")
+ names += i + ": " + obj.value + "\n";
+ else if (i == "id")
+ names += i + ": " + obj.id + "\n";
+ else
+ names += i + "\n";
+ }
+
+ dump(names + "-----------\n");
+}
+
+//-----------------------------------------------------------------------------------
+function PrintNodeID(id)
+{
+ PrintObject(document.getElementById(id));
+}
+
+//-----------------------------------------------------------------------------------
+var nsDummyHTMLCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // do nothing
+ dump("Hey, who's calling the dummy command?\n");
+ }
+
+};
+
+//-----------------------------------------------------------------------------------
+var nsOpenCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true; // we can always do this
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ fp.init(window, GetString("OpenHTMLFile"), nsIFilePicker.modeOpen);
+
+ SetFilePickerDirectory(fp, "html");
+
+ // When loading into Composer, direct user to prefer HTML files and text files,
+ // so we call separately to control the order of the filter list
+ fp.appendFilters(nsIFilePicker.filterHTML);
+ fp.appendFilters(nsIFilePicker.filterText);
+ fp.appendFilters(nsIFilePicker.filterAll);
+
+ /* doesn't handle *.shtml files */
+ try {
+ fp.show();
+ /* need to handle cancel (uncaught exception at present) */
+ }
+ catch (ex) {
+ dump("filePicker.chooseInputFile threw an exception\n");
+ }
+
+ /* This checks for already open window and activates it...
+ * note that we have to test the native path length
+ * since file.URL will be "file:///" if no filename picked (Cancel button used)
+ */
+ if (fp.file && fp.file.path.length > 0) {
+ SaveFilePickerDirectory(fp, "html");
+ editPage(fp.fileURL.spec, window, false);
+ }
+ }
+};
+
+// STRUCTURE TOOLBAR
+//
+var nsUpdateStructToolbarCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ UpdateStructToolbar();
+ return true;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+ doCommand: function(aCommand) {}
+}
+
+// ******* File output commands and utilities ******** //
+//-----------------------------------------------------------------------------------
+var nsSaveCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ // Always allow saving when editing a remote document,
+ // otherwise the document modified state would prevent that
+ // when you first open a remote file.
+ try {
+ var docUrl = GetDocumentUrl();
+ return IsDocumentEditable() &&
+ (IsDocumentModified() || IsHTMLSourceChanged() ||
+ IsUrlAboutBlank(docUrl) || GetScheme(docUrl) != "file");
+ } catch (e) {return false;}
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var result = false;
+ var editor = GetCurrentEditor();
+ if (editor)
+ {
+ FinishHTMLSource();
+ result = SaveDocument(IsUrlAboutBlank(GetDocumentUrl()), false, editor.contentsMIMEType);
+ window.content.focus();
+ }
+ return result;
+ }
+}
+
+var nsSaveAsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var editor = GetCurrentEditor();
+ if (editor)
+ {
+ FinishHTMLSource();
+ var result = SaveDocument(true, false, editor.contentsMIMEType);
+ window.content.focus();
+ return result;
+ }
+ return false;
+ }
+}
+
+var nsExportToTextCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (GetCurrentEditor())
+ {
+ FinishHTMLSource();
+ var result = SaveDocument(true, true, "text/plain");
+ window.content.focus();
+ return result;
+ }
+ return false;
+ }
+}
+
+var nsSaveAndChangeEncodingCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ FinishHTMLSource();
+ window.ok = false;
+ window.exportToText = false;
+ var oldTitle = GetDocumentTitle();
+ window.openDialog("chrome://editor/content/EditorSaveAsCharset.xul","_blank", "chrome,close,titlebar,modal,resizable=yes");
+
+ if (GetDocumentTitle() != oldTitle)
+ UpdateWindowTitle();
+
+ if (window.ok)
+ {
+ if (window.exportToText)
+ {
+ window.ok = SaveDocument(true, true, "text/plain");
+ }
+ else
+ {
+ var editor = GetCurrentEditor();
+ window.ok = SaveDocument(true, false, editor ? editor.contentsMIMEType : null);
+ }
+ }
+
+ window.content.focus();
+ return window.ok;
+ }
+};
+
+var nsPublishCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ if (IsDocumentEditable())
+ {
+ // Always allow publishing when editing a local document,
+ // otherwise the document modified state would prevent that
+ // when you first open any local file.
+ try {
+ var docUrl = GetDocumentUrl();
+ return IsDocumentModified() || IsHTMLSourceChanged()
+ || IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file";
+ } catch (e) {return false;}
+ }
+ return false;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (GetCurrentEditor())
+ {
+ var docUrl = GetDocumentUrl();
+ var filename = GetFilename(docUrl);
+ var publishData;
+ var showPublishDialog = false;
+
+ // First check pref to always show publish dialog
+ try {
+ var prefs = GetPrefs();
+ if (prefs)
+ showPublishDialog = prefs.getBoolPref("editor.always_show_publish_dialog");
+ } catch(e) {}
+
+ if (!showPublishDialog && filename)
+ {
+ // Try to get publish data from the document url
+ publishData = CreatePublishDataFromUrl(docUrl);
+
+ // If none, use default publishing site? Need a pref for this
+ //if (!publishData)
+ // publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
+ }
+
+ if (showPublishDialog || !publishData)
+ {
+ // Show the publish dialog
+ publishData = {};
+ window.ok = false;
+ var oldTitle = GetDocumentTitle();
+ window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
+ "chrome,close,titlebar,modal", "", "", publishData);
+ if (GetDocumentTitle() != oldTitle)
+ UpdateWindowTitle();
+
+ window.content.focus();
+ if (!window.ok)
+ return false;
+ }
+ if (publishData)
+ {
+ FinishHTMLSource();
+ return Publish(publishData);
+ }
+ }
+ return false;
+ }
+}
+
+var nsPublishAsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (GetCurrentEditor())
+ {
+ FinishHTMLSource();
+
+ window.ok = false;
+ var publishData = {};
+ var oldTitle = GetDocumentTitle();
+ window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
+ "chrome,close,titlebar,modal", "", "", publishData);
+ if (GetDocumentTitle() != oldTitle)
+ UpdateWindowTitle();
+
+ window.content.focus();
+ if (window.ok)
+ return Publish(publishData);
+ }
+ return false;
+ }
+}
+
+// ------- output utilites ----- //
+
+// returns a fileExtension string
+function GetExtensionBasedOnMimeType(aMIMEType)
+{
+ try {
+ var mimeService = null;
+ mimeService = Components.classes["@mozilla.org/mime;1"].getService();
+ mimeService = mimeService.QueryInterface(Components.interfaces.nsIMIMEService);
+
+ var fileExtension = mimeService.getPrimaryExtension(aMIMEType, null);
+
+ // the MIME service likes to give back ".htm" for text/html files,
+ // so do a special-case fix here.
+ if (fileExtension == "htm")
+ fileExtension = "html";
+
+ return fileExtension;
+ }
+ catch (e) {}
+ return "";
+}
+
+function GetSuggestedFileName(aDocumentURLString, aMIMEType)
+{
+ var extension = GetExtensionBasedOnMimeType(aMIMEType);
+ if (extension)
+ extension = "." + extension;
+
+ // check for existing file name we can use
+ if (aDocumentURLString.length >= 0 && !IsUrlAboutBlank(aDocumentURLString))
+ {
+ var docURI = null;
+ try {
+
+ var ioService = GetIOService();
+ docURI = ioService.newURI(aDocumentURLString, GetCurrentEditor().documentCharacterSet, null);
+ docURI = docURI.QueryInterface(Components.interfaces.nsIURL);
+
+ // grab the file name
+ var url = docURI.fileBaseName;
+ if (url)
+ return url+extension;
+ } catch(e) {}
+ }
+
+ // check if there is a title we can use
+ var title = GetDocumentTitle();
+ // generate a valid filename, if we can't just go with "untitled"
+ return GenerateValidFilename(title, extension) || GetString("untitled") + extension;
+}
+
+// returns file picker result
+function PromptForSaveLocation(aDoSaveAsText, aEditorType, aMIMEType, aDocumentURLString)
+{
+ var dialogResult = {};
+ dialogResult.filepickerClick = nsIFilePicker.returnCancel;
+ dialogResult.resultingURI = "";
+ dialogResult.resultingLocalFile = null;
+
+ var fp = null;
+ try {
+ fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ } catch (e) {}
+ if (!fp) return dialogResult;
+
+ // determine prompt string based on type of saving we'll do
+ var promptString;
+ if (aDoSaveAsText || aEditorType == "text")
+ promptString = GetString("ExportToText");
+ else
+ promptString = GetString("SaveDocumentAs")
+
+ fp.init(window, promptString, nsIFilePicker.modeSave);
+
+ // Set filters according to the type of output
+ if (aDoSaveAsText)
+ fp.appendFilters(nsIFilePicker.filterText);
+ else
+ fp.appendFilters(nsIFilePicker.filterHTML);
+ fp.appendFilters(nsIFilePicker.filterAll);
+
+ // now let's actually set the filepicker's suggested filename
+ var suggestedFileName = GetSuggestedFileName(aDocumentURLString, aMIMEType);
+ if (suggestedFileName)
+ fp.defaultString = suggestedFileName;
+
+ // set the file picker's current directory
+ // assuming we have information needed (like prior saved location)
+ try {
+ var ioService = GetIOService();
+ var fileHandler = GetFileProtocolHandler();
+
+ var isLocalFile = true;
+ try {
+ var docURI = ioService.newURI(aDocumentURLString, GetCurrentEditor().documentCharacterSet, null);
+ isLocalFile = docURI.schemeIs("file");
+ }
+ catch (e) {}
+
+ var parentLocation = null;
+ if (isLocalFile)
+ {
+ var fileLocation = fileHandler.getFileFromURLSpec(aDocumentURLString); // this asserts if url is not local
+ parentLocation = fileLocation.parent;
+ }
+ if (parentLocation)
+ {
+ // Save current filepicker's default location
+ if ("gFilePickerDirectory" in window)
+ gFilePickerDirectory = fp.displayDirectory;
+
+ fp.displayDirectory = parentLocation;
+ }
+ else
+ {
+ // Initialize to the last-used directory for the particular type (saved in prefs)
+ SetFilePickerDirectory(fp, aEditorType);
+ }
+ }
+ catch(e) {}
+
+ dialogResult.filepickerClick = fp.show();
+ if (dialogResult.filepickerClick != nsIFilePicker.returnCancel)
+ {
+ // reset urlstring to new save location
+ dialogResult.resultingURIString = fileHandler.getURLSpecFromFile(fp.file);
+ dialogResult.resultingLocalFile = fp.file;
+ SaveFilePickerDirectory(fp, aEditorType);
+ }
+ else if ("gFilePickerDirectory" in window && gFilePickerDirectory)
+ fp.displayDirectory = gFilePickerDirectory;
+
+ return dialogResult;
+}
+
+// returns a boolean (whether to continue (true) or not (false) because user canceled)
+function PromptAndSetTitleIfNone()
+{
+ if (GetDocumentTitle()) // we have a title; no need to prompt!
+ return true;
+
+ var promptService = GetPromptService();
+ if (!promptService) return false;
+
+ var result = {value:null};
+ var captionStr = GetString("DocumentTitle");
+ var msgStr = GetString("NeedDocTitle") + '\n' + GetString("DocTitleHelp");
+ var confirmed = promptService.prompt(window, captionStr, msgStr, result, null, {value:0});
+ if (confirmed)
+ SetDocumentTitle(TrimString(result.value));
+
+ return confirmed;
+}
+
+var gPersistObj;
+
+// Don't forget to do these things after calling OutputFileWithPersistAPI:
+// we need to update the uri before notifying listeners
+// if (doUpdateURI)
+// SetDocumentURI(docURI);
+// UpdateWindowTitle();
+// if (!aSaveCopy)
+// editor.resetModificationCount();
+ // this should cause notification to listeners that document has changed
+
+const webPersist = Components.interfaces.nsIWebBrowserPersist;
+function OutputFileWithPersistAPI(editorDoc, aDestinationLocation, aRelatedFilesParentDir, aMimeType)
+{
+ gPersistObj = null;
+ var editor = GetCurrentEditor();
+ try {
+ var imeEditor = editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
+ imeEditor.forceCompositionEnd();
+ } catch (e) {}
+
+ var isLocalFile = false;
+ try {
+ var tmp1 = aDestinationLocation.QueryInterface(Components.interfaces.nsIFile);
+ isLocalFile = true;
+ }
+ catch (e) {
+ try {
+ var tmp = aDestinationLocation.QueryInterface(Components.interfaces.nsIURI);
+ isLocalFile = tmp.schemeIs("file");
+ }
+ catch (e) {}
+ }
+
+ try {
+ // we should supply a parent directory if/when we turn on functionality to save related documents
+ var persistObj = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(webPersist);
+ persistObj.progressListener = gEditorOutputProgressListener;
+
+ var wrapColumn = GetWrapColumn();
+ var outputFlags = GetOutputFlags(aMimeType, wrapColumn);
+
+ // for 4.x parity as well as improving readability of file locally on server
+ // this will always send crlf for upload (http/ftp)
+ if (!isLocalFile) // if we aren't saving locally then send both cr and lf
+ {
+ outputFlags |= webPersist.ENCODE_FLAGS_CR_LINEBREAKS | webPersist.ENCODE_FLAGS_LF_LINEBREAKS;
+
+ // we want to serialize the output for all remote publishing
+ // some servers can handle only one connection at a time
+ // some day perhaps we can make this user-configurable per site?
+ persistObj.persistFlags = persistObj.persistFlags | webPersist.PERSIST_FLAGS_SERIALIZE_OUTPUT;
+ }
+
+ // note: we always want to set the replace existing files flag since we have
+ // already given user the chance to not replace an existing file (file picker)
+ // or the user picked an option where the file is implicitly being replaced (save)
+ persistObj.persistFlags = persistObj.persistFlags
+ | webPersist.PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS
+ | webPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES
+ | webPersist.PERSIST_FLAGS_DONT_FIXUP_LINKS
+ | webPersist.PERSIST_FLAGS_DONT_CHANGE_FILENAMES
+ | webPersist.PERSIST_FLAGS_FIXUP_ORIGINAL_DOM;
+ persistObj.saveDocument(editorDoc, aDestinationLocation, aRelatedFilesParentDir,
+ aMimeType, outputFlags, wrapColumn);
+ gPersistObj = persistObj;
+ }
+ catch(e) { dump("caught an error, bail\n"); return false; }
+
+ return true;
+}
+
+// returns output flags based on mimetype, wrapCol and prefs
+function GetOutputFlags(aMimeType, aWrapColumn)
+{
+ var outputFlags = 0;
+ var editor = GetCurrentEditor();
+ var outputEntity = (editor && editor.documentCharacterSet == "ISO-8859-1")
+ ? webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES
+ : webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES;
+ if (aMimeType == "text/plain")
+ {
+ // When saving in "text/plain" format, always do formatting
+ outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
+ }
+ else
+ {
+ try {
+ // Should we prettyprint? Check the pref
+ var prefs = GetPrefs();
+ if (prefs.getBoolPref("editor.prettyprint"))
+ outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
+
+ // How much entity names should we output? Check the pref
+ var encodeEntity = prefs.getCharPref("editor.encode_entity");
+ switch (encodeEntity) {
+ case "basic" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES; break;
+ case "latin1" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES; break;
+ case "html" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_HTML_ENTITIES; break;
+ case "none" : outputEntity = 0; break;
+ }
+ }
+ catch (e) {}
+ }
+ outputFlags |= outputEntity;
+
+ if (aWrapColumn > 0)
+ outputFlags |= webPersist.ENCODE_FLAGS_WRAP;
+
+ return outputFlags;
+}
+
+// returns number of column where to wrap
+const nsIWebBrowserPersist = Components.interfaces.nsIWebBrowserPersist;
+function GetWrapColumn()
+{
+ try {
+ return GetCurrentEditor().wrapWidth;
+ } catch (e) {}
+ return 0;
+}
+
+function GetPromptService()
+{
+ var promptService;
+ try {
+ promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
+ promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
+ }
+ catch (e) {}
+ return promptService;
+}
+
+const gShowDebugOutputStateChange = false;
+const gShowDebugOutputProgress = false;
+const gShowDebugOutputStatusChange = false;
+
+const gShowDebugOutputLocationChange = false;
+const gShowDebugOutputSecurityChange = false;
+
+const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
+const nsIChannel = Components.interfaces.nsIChannel;
+
+const kErrorBindingAborted = 2152398850;
+const kErrorBindingRedirected = 2152398851;
+const kFileNotFound = 2152857618;
+
+var gEditorOutputProgressListener =
+{
+ onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
+ {
+ var editor = GetCurrentEditor();
+
+ // Use this to access onStateChange flags
+ var requestSpec;
+ try {
+ var channel = aRequest.QueryInterface(nsIChannel);
+ requestSpec = StripUsernamePasswordFromURI(channel.URI);
+ } catch (e) {
+ if ( gShowDebugOutputStateChange)
+ dump("***** onStateChange; NO REQUEST CHANNEL\n");
+ }
+
+ var pubSpec;
+ if (gPublishData)
+ pubSpec = gPublishData.publishUrl + gPublishData.docDir + gPublishData.filename;
+
+ if (gShowDebugOutputStateChange)
+ {
+ dump("\n***** onStateChange request: " + requestSpec + "\n");
+ dump(" state flags: ");
+
+ if (aStateFlags & nsIWebProgressListener.STATE_START)
+ dump(" STATE_START, ");
+ if (aStateFlags & nsIWebProgressListener.STATE_STOP)
+ dump(" STATE_STOP, ");
+ if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)
+ dump(" STATE_IS_NETWORK ");
+
+ dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n");
+
+ DumpDebugStatus(aStatus);
+ }
+ // The rest only concerns publishing, so bail out if no dialog
+ if (!gProgressDialog)
+ return;
+
+ // Detect start of file upload of any file:
+ // (We ignore any START messages after gPersistObj says publishing is finished
+ if ((aStateFlags & nsIWebProgressListener.STATE_START)
+ && gPersistObj && requestSpec
+ && (gPersistObj.currentState != gPersistObj.PERSIST_STATE_FINISHED))
+ {
+ try {
+ // Add url to progress dialog's list showing each file uploading
+ gProgressDialog.SetProgressStatus(GetFilename(requestSpec), "busy");
+ } catch(e) {}
+ }
+
+ // Detect end of file upload of any file:
+ if (aStateFlags & nsIWebProgressListener.STATE_STOP)
+ {
+ // ignore aStatus == kErrorBindingAborted; check http response for possible errors
+ try {
+ // check http channel for response: 200 range is ok; other ranges are not
+ var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+ var httpResponse = httpChannel.responseStatus;
+ if (httpResponse < 200 || httpResponse >= 300)
+ aStatus = httpResponse; // not a real error but enough to pass check below
+ else if (aStatus == kErrorBindingAborted)
+ aStatus = 0;
+
+ if (gShowDebugOutputStateChange)
+ dump("http response is: "+httpResponse+"\n");
+ }
+ catch(e)
+ {
+ if (aStatus == kErrorBindingAborted)
+ aStatus = 0;
+ }
+
+ // We abort publishing for all errors except if image src file is not found
+ var abortPublishing = (aStatus != 0 && aStatus != kFileNotFound);
+
+ // Notify progress dialog when we receive the STOP
+ // notification for a file if there was an error
+ // or a successful finish
+ // (Check requestSpec to be sure message is for destination url)
+ if (aStatus != 0
+ || (requestSpec && requestSpec.indexOf(GetScheme(gPublishData.publishUrl)) == 0))
+ {
+ try {
+ gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus);
+ } catch(e) {}
+ }
+
+
+ if (abortPublishing)
+ {
+ // Cancel publishing
+ gPersistObj.cancelSave();
+
+ // Don't do any commands after failure
+ gCommandAfterPublishing = null;
+
+ // Restore original document to undo image src url adjustments
+ if (gRestoreDocumentSource)
+ {
+ try {
+ editor.rebuildDocumentFromSource(gRestoreDocumentSource);
+
+ // Clear transaction cache since we just did a potentially
+ // very large insert and this will eat up memory
+ editor.transactionManager.clear();
+ }
+ catch (e) {}
+ }
+
+ // Notify progress dialog that we're finished
+ // and keep open to show error
+ gProgressDialog.SetProgressFinished(null, 0);
+
+ // We don't want to change location or reset mod count, etc.
+ return;
+ }
+
+ //XXX HACK: "file://" protocol is not supported in network code
+ // (bug 151867 filed to add this support, bug 151869 filed
+ // to remove this and other code in nsIWebBrowserPersist)
+ // nsIWebBrowserPersist *does* copy the file(s), but we don't
+ // get normal onStateChange messages.
+
+ // Case 1: If images are included, we get fairly normal
+ // STATE_START/STATE_STOP & STATE_IS_NETWORK messages associated with the image files,
+ // thus we must finish HTML file progress below
+
+ // Case 2: If just HTML file is uploaded, we get STATE_START and STATE_STOP
+ // notification with a null "requestSpec", and
+ // the gPersistObj is destroyed before we get here!
+ // So create an new object so we can flow through normal processing below
+ if (!requestSpec && GetScheme(gPublishData.publishUrl) == "file"
+ && (!gPersistObj || gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED))
+ {
+ aStateFlags |= nsIWebProgressListener.STATE_IS_NETWORK;
+ if (!gPersistObj)
+ {
+ gPersistObj =
+ {
+ result : aStatus,
+ currentState : nsIWebBrowserPersist.PERSIST_STATE_FINISHED
+ }
+ }
+ }
+
+ // STATE_IS_NETWORK signals end of publishing, as does the gPersistObj.currentState
+ if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK
+ && gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED)
+ {
+ if (GetScheme(gPublishData.publishUrl) == "file")
+ {
+ //XXX "file://" hack: We don't get notified about the HTML file, so end progress for it
+ // (This covers both "Case 1 and 2" described above)
+ gProgressDialog.SetProgressFinished(gPublishData.filename, gPersistObj.result);
+ }
+
+ if (gPersistObj.result == 0)
+ {
+ // All files are finished and publishing succeeded (some images may have failed)
+ try {
+ // Make a new docURI from the "browse location" in case "publish location" was FTP
+ // We need to set document uri before notifying listeners
+ var docUrl = GetDocUrlFromPublishData(gPublishData);
+ SetDocumentURI(GetIOService().newURI(docUrl, editor.documentCharacterSet, null));
+
+ UpdateWindowTitle();
+
+ // this should cause notification to listeners that doc has changed
+ editor.resetModificationCount();
+
+ // Set UI based on whether we're editing a remote or local url
+ SetSaveAndPublishUI(urlstring);
+
+ } catch (e) {}
+
+ // Save publishData to prefs
+ if (gPublishData)
+ {
+ if (gPublishData.savePublishData)
+ {
+ // We published successfully, so we can safely
+ // save docDir and otherDir to prefs
+ gPublishData.saveDirs = true;
+ SavePublishDataToPrefs(gPublishData);
+ }
+ else
+ SavePassword(gPublishData);
+ }
+
+ // Ask progress dialog to close, but it may not
+ // if user checked checkbox to keep it open
+ gProgressDialog.RequestCloseDialog();
+ }
+ else
+ {
+ // We previously aborted publishing because of error:
+ // Calling gPersistObj.cancelSave() resulted in a non-zero gPersistObj.result,
+ // so notify progress dialog we're finished
+ gProgressDialog.SetProgressFinished(null, 0);
+ }
+ }
+ }
+ },
+
+ onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
+ aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
+ {
+ if (!gPersistObj)
+ return;
+
+ if (gShowDebugOutputProgress)
+ {
+ dump("\n onProgressChange: gPersistObj.result="+gPersistObj.result+"\n");
+ try {
+ var channel = aRequest.QueryInterface(nsIChannel);
+ dump("***** onProgressChange request: " + channel.URI.spec + "\n");
+ }
+ catch (e) {}
+ dump("***** self: "+aCurSelfProgress+" / "+aMaxSelfProgress+"\n");
+ dump("***** total: "+aCurTotalProgress+" / "+aMaxTotalProgress+"\n\n");
+
+ if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
+ dump(" Persister is ready to save data\n\n");
+ else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
+ dump(" Persister is saving data.\n\n");
+ else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
+ dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
+ }
+ },
+
+ onLocationChange : function(aWebProgress, aRequest, aLocation)
+ {
+ if (gShowDebugOutputLocationChange)
+ {
+ dump("***** onLocationChange: "+aLocation.spec+"\n");
+ try {
+ var channel = aRequest.QueryInterface(nsIChannel);
+ dump("***** request: " + channel.URI.spec + "\n");
+ }
+ catch(e) {}
+ }
+ },
+
+ onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
+ {
+ if (gShowDebugOutputStatusChange)
+ {
+ dump("***** onStatusChange: "+aMessage+"\n");
+ try {
+ var channel = aRequest.QueryInterface(nsIChannel);
+ dump("***** request: " + channel.URI.spec + "\n");
+ }
+ catch (e) { dump(" couldn't get request\n"); }
+
+ DumpDebugStatus(aStatus);
+
+ if (gPersistObj)
+ {
+ if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
+ dump(" Persister is ready to save data\n\n");
+ else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
+ dump(" Persister is saving data.\n\n");
+ else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
+ dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
+ }
+ }
+ },
+
+ onSecurityChange : function(aWebProgress, aRequest, state)
+ {
+ if (gShowDebugOutputSecurityChange)
+ {
+ try {
+ var channel = aRequest.QueryInterface(nsIChannel);
+ dump("***** onSecurityChange request: " + channel.URI.spec + "\n");
+ } catch (e) {}
+ }
+ },
+
+ QueryInterface : function(aIID)
+ {
+ if (aIID.equals(Components.interfaces.nsIWebProgressListener)
+ || aIID.equals(Components.interfaces.nsISupports)
+ || aIID.equals(Components.interfaces.nsISupportsWeakReference)
+ || aIID.equals(Components.interfaces.nsIPrompt)
+ || aIID.equals(Components.interfaces.nsIAuthPrompt))
+ return this;
+ throw Components.results.NS_NOINTERFACE;
+ },
+
+// nsIPrompt
+ alert : function(dlgTitle, text)
+ {
+ AlertWithTitle(dlgTitle, text, gProgressDialog ? gProgressDialog : window);
+ },
+ alertCheck : function(dialogTitle, text, checkBoxLabel, checkObj)
+ {
+ AlertWithTitle(dialogTitle, text);
+ },
+ confirm : function(dlgTitle, text)
+ {
+ return ConfirmWithTitle(dlgTitle, text, null, null);
+ },
+ confirmCheck : function(dlgTitle, text, checkBoxLabel, checkObj)
+ {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return;
+
+ promptServ.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS,
+ "", "", "", checkBoxLabel, checkObj);
+ },
+ confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal)
+ {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return 0;
+
+ return promptServ.confirmEx(window, dlgTitle, text, btnFlags,
+ btn0Title, btn1Title, btn2Title,
+ checkBoxLabel, checkVal);
+ },
+ prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkObj)
+ {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkObj);
+ },
+ promptPassword : function(dlgTitle, text, pwObj, checkBoxLabel, savePWObj)
+ {
+
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ var ret = false;
+ try {
+ // Note difference with nsIAuthPrompt::promptPassword, which has
+ // just "in" savePassword param, while nsIPrompt is "inout"
+ // Initialize with user's previous preference for this site
+ if (gPublishData)
+ savePWObj.value = gPublishData.savePassword;
+
+ ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
+ dlgTitle, text, pwObj, checkBoxLabel, savePWObj);
+
+ if (!ret)
+ setTimeout(CancelPublishing, 0);
+
+ if (ret && gPublishData)
+ UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
+ } catch(e) {}
+
+ return ret;
+ },
+ promptUsernameAndPassword : function(dlgTitle, text, userObj, pwObj, checkBoxLabel, savePWObj)
+ {
+ var ret = PromptUsernameAndPassword(dlgTitle, text, savePWObj.value, userObj, pwObj);
+ if (!ret)
+ setTimeout(CancelPublishing, 0);
+
+ return ret;
+ },
+ select : function(dlgTitle, text, count, selectList, outSelection)
+ {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ return promptServ.select(window, dlgTitle, text, count, selectList, outSelection);
+ },
+
+// nsIAuthPrompt
+ prompt : function(dlgTitle, text, pwrealm, savePW, defaultText, result)
+ {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ var savePWObj = {value:savePW};
+ var ret = promptServ.prompt(gProgressDialog ? gProgressDialog : window,
+ dlgTitle, text, defaultText, pwrealm, savePWObj);
+ if (!ret)
+ setTimeout(CancelPublishing, 0);
+ return ret;
+ },
+
+ promptUsernameAndPassword : function(dlgTitle, text, pwrealm, savePW, userObj, pwObj)
+ {
+ var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj);
+ if (!ret)
+ setTimeout(CancelPublishing, 0);
+ return ret;
+ },
+
+ promptPassword : function(dlgTitle, text, pwrealm, savePW, pwObj)
+ {
+ var ret = false;
+ try {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ // Note difference with nsIPrompt::promptPassword, which has
+ // "inout" savePassword param, while nsIAuthPrompt is just "in"
+ // Also nsIAuth doesn't supply "checkBoxLabel"
+ // Initialize with user's previous preference for this site
+ var savePWObj = {value:savePW};
+ // Initialize with user's previous preference for this site
+ if (gPublishData)
+ savePWObj.value = gPublishData.savePassword;
+
+ ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
+ dlgTitle, text, pwObj, GetString("SavePassword"), savePWObj);
+
+ if (!ret)
+ setTimeout(CancelPublishing, 0);
+
+ if (ret && gPublishData)
+ UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
+ } catch(e) {}
+
+ return ret;
+ }
+}
+
+function PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj)
+{
+ // HTTP prompts us twice even if user Cancels from 1st attempt!
+ // So never put up dialog if there's no publish data
+ if (!gPublishData)
+ return false
+
+ var ret = false;
+ try {
+ var promptServ = GetPromptService();
+ if (!promptServ)
+ return false;
+
+ var savePWObj = {value:savePW};
+
+ // Initialize with user's previous preference for this site
+ if (gPublishData)
+ {
+ // HTTP put uses this dialog if either username or password is bad,
+ // so prefill username input field with the previous value for modification
+ savePWObj.value = gPublishData.savePassword;
+ if (!userObj.value)
+ userObj.value = gPublishData.username;
+ }
+
+ ret = promptServ.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window,
+ dlgTitle, text, userObj, pwObj,
+ GetString("SavePassword"), savePWObj);
+ if (ret && gPublishData)
+ UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, savePWObj.value);
+
+ } catch (e) {}
+
+ return ret;
+}
+
+function DumpDebugStatus(aStatus)
+{
+ // see nsError.h and netCore.h and ftpCore.h
+
+ if (aStatus == kErrorBindingAborted)
+ dump("***** status is NS_BINDING_ABORTED\n");
+ else if (aStatus == kErrorBindingRedirected)
+ dump("***** status is NS_BINDING_REDIRECTED\n");
+ else if (aStatus == 2152398859) // in netCore.h 11
+ dump("***** status is ALREADY_CONNECTED\n");
+ else if (aStatus == 2152398860) // in netCore.h 12
+ dump("***** status is NOT_CONNECTED\n");
+ else if (aStatus == 2152398861) // in nsISocketTransportService.idl 13
+ dump("***** status is CONNECTION_REFUSED\n");
+ else if (aStatus == 2152398862) // in nsISocketTransportService.idl 14
+ dump("***** status is NET_TIMEOUT\n");
+ else if (aStatus == 2152398863) // in netCore.h 15
+ dump("***** status is IN_PROGRESS\n");
+ else if (aStatus == 2152398864) // 0x804b0010 in netCore.h 16
+ dump("***** status is OFFLINE\n");
+ else if (aStatus == 2152398865) // in netCore.h 17
+ dump("***** status is NO_CONTENT\n");
+ else if (aStatus == 2152398866) // in netCore.h 18
+ dump("***** status is UNKNOWN_PROTOCOL\n");
+ else if (aStatus == 2152398867) // in netCore.h 19
+ dump("***** status is PORT_ACCESS_NOT_ALLOWED\n");
+ else if (aStatus == 2152398868) // in nsISocketTransportService.idl 20
+ dump("***** status is NET_RESET\n");
+ else if (aStatus == 2152398869) // in ftpCore.h 21
+ dump("***** status is FTP_LOGIN\n");
+ else if (aStatus == 2152398870) // in ftpCore.h 22
+ dump("***** status is FTP_CWD\n");
+ else if (aStatus == 2152398871) // in ftpCore.h 23
+ dump("***** status is FTP_PASV\n");
+ else if (aStatus == 2152398872) // in ftpCore.h 24
+ dump("***** status is FTP_PWD\n");
+ else if (aStatus == 2152857601)
+ dump("***** status is UNRECOGNIZED_PATH\n");
+ else if (aStatus == 2152857602)
+ dump("***** status is UNRESOLABLE SYMLINK\n");
+ else if (aStatus == 2152857604)
+ dump("***** status is UNKNOWN_TYPE\n");
+ else if (aStatus == 2152857605)
+ dump("***** status is DESTINATION_NOT_DIR\n");
+ else if (aStatus == 2152857606)
+ dump("***** status is TARGET_DOES_NOT_EXIST\n");
+ else if (aStatus == 2152857608)
+ dump("***** status is ALREADY_EXISTS\n");
+ else if (aStatus == 2152857609)
+ dump("***** status is INVALID_PATH\n");
+ else if (aStatus == 2152857610)
+ dump("***** status is DISK_FULL\n");
+ else if (aStatus == 2152857612)
+ dump("***** status is NOT_DIRECTORY\n");
+ else if (aStatus == 2152857613)
+ dump("***** status is IS_DIRECTORY\n");
+ else if (aStatus == 2152857614)
+ dump("***** status is IS_LOCKED\n");
+ else if (aStatus == 2152857615)
+ dump("***** status is TOO_BIG\n");
+ else if (aStatus == 2152857616)
+ dump("***** status is NO_DEVICE_SPACE\n");
+ else if (aStatus == 2152857617)
+ dump("***** status is NAME_TOO_LONG\n");
+ else if (aStatus == 2152857618) // 80520012
+ dump("***** status is FILE_NOT_FOUND\n");
+ else if (aStatus == 2152857619)
+ dump("***** status is READ_ONLY\n");
+ else if (aStatus == 2152857620)
+ dump("***** status is DIR_NOT_EMPTY\n");
+ else if (aStatus == 2152857621)
+ dump("***** status is ACCESS_DENIED\n");
+ else if (aStatus == 2152398878)
+ dump("***** status is ? (No connection or time out?)\n");
+ else
+ dump("***** status is " + aStatus + "\n");
+}
+
+// Update any data that the user supplied in a prompt dialog
+function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword)
+{
+ if (!publishData)
+ return;
+
+ // Set flag to save publish data after publishing if it changed in dialog
+ // and the "SavePassword" checkbox was checked
+ // or we already had site data for this site
+ // (Thus we don't automatically create a site until user brings up Publish As dialog)
+ publishData.savePublishData = (gPublishData.username != username || gPublishData.password != password)
+ && (savePassword || !publishData.notInSiteData);
+
+ publishData.username = username;
+ publishData.password = password;
+ publishData.savePassword = savePassword;
+}
+
+const kSupportedTextMimeTypes =
+[
+ "text/plain",
+ "text/css",
+ "text/rdf",
+ "text/xsl",
+ "text/javascript",
+ "text/ecmascript",
+ "application/javascript",
+ "application/ecmascript",
+ "application/x-javascript",
+ "text/xul",
+ "application/vnd.mozilla.xul+xml"
+];
+
+function IsSupportedTextMimeType(aMimeType)
+{
+ for (var i = 0; i < kSupportedTextMimeTypes.length; i++)
+ {
+ if (kSupportedTextMimeTypes[i] == aMimeType)
+ return true;
+ }
+ return false;
+}
+
+// throws an error or returns true if user attempted save; false if user canceled save
+function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
+{
+ var editor = GetCurrentEditor();
+ if (!aMimeType || aMimeType == "" || !editor)
+ throw Components.results.NS_ERROR_NOT_INITIALIZED;
+
+ var editorDoc = editor.document;
+ if (!editorDoc)
+ throw Components.results.NS_ERROR_NOT_INITIALIZED;
+
+ // if we don't have the right editor type bail (we handle text and html)
+ var editorType = GetCurrentEditorType();
+ if (editorType != "text" && editorType != "html"
+ && editorType != "htmlmail" && editorType != "textmail")
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+
+ var saveAsTextFile = IsSupportedTextMimeType(aMimeType);
+
+ // check if the file is to be saved is a format we don't understand; if so, bail
+ if (aMimeType != "text/html" && !saveAsTextFile)
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+
+ if (saveAsTextFile)
+ aMimeType = "text/plain";
+
+ var urlstring = GetDocumentUrl();
+ var mustShowFileDialog = (aSaveAs || IsUrlAboutBlank(urlstring) || (urlstring == ""));
+
+ // If editing a remote URL, force SaveAs dialog
+ if (!mustShowFileDialog && GetScheme(urlstring) != "file")
+ mustShowFileDialog = true;
+
+ var replacing = !aSaveAs;
+ var titleChanged = false;
+ var doUpdateURI = false;
+ var tempLocalFile = null;
+
+ if (mustShowFileDialog)
+ {
+ try {
+ // Prompt for title if we are saving to HTML
+ if (!saveAsTextFile && (editorType == "html"))
+ {
+ var userContinuing = PromptAndSetTitleIfNone(); // not cancel
+ if (!userContinuing)
+ return false;
+ }
+
+ var dialogResult = PromptForSaveLocation(saveAsTextFile, editorType, aMimeType, urlstring);
+ if (dialogResult.filepickerClick == nsIFilePicker.returnCancel)
+ return false;
+
+ replacing = (dialogResult.filepickerClick == nsIFilePicker.returnReplace);
+ urlstring = dialogResult.resultingURIString;
+ tempLocalFile = dialogResult.resultingLocalFile;
+
+ // update the new URL for the webshell unless we are saving a copy
+ if (!aSaveCopy)
+ doUpdateURI = true;
+ } catch (e) { return false; }
+ } // mustShowFileDialog
+
+ var success = true;
+ var ioService;
+ try {
+ // if somehow we didn't get a local file but we did get a uri,
+ // attempt to create the localfile if it's a "file" url
+ var docURI;
+ if (!tempLocalFile)
+ {
+ ioService = GetIOService();
+ docURI = ioService.newURI(urlstring, editor.documentCharacterSet, null);
+
+ if (docURI.schemeIs("file"))
+ {
+ var fileHandler = GetFileProtocolHandler();
+ tempLocalFile = fileHandler.getFileFromURLSpec(urlstring).QueryInterface(Components.interfaces.nsILocalFile);
+ }
+ }
+
+ // this is the location where the related files will go
+ var relatedFilesDir = null;
+
+ // First check pref for saving associated files
+ var saveAssociatedFiles = false;
+ try {
+ var prefs = GetPrefs();
+ saveAssociatedFiles = prefs.getBoolPref("editor.save_associated_files");
+ } catch (e) {}
+
+ // Only change links or move files if pref is set
+ // and we are saving to a new location
+ if (saveAssociatedFiles && aSaveAs)
+ {
+ try {
+ if (tempLocalFile)
+ {
+ // if we are saving to the same parent directory, don't set relatedFilesDir
+ // grab old location, chop off file
+ // grab new location, chop off file, compare
+ var oldLocation = GetDocumentUrl();
+ var oldLocationLastSlash = oldLocation.lastIndexOf("\/");
+ if (oldLocationLastSlash != -1)
+ oldLocation = oldLocation.slice(0, oldLocationLastSlash);
+
+ var relatedFilesDirStr = urlstring;
+ var newLocationLastSlash = relatedFilesDirStr.lastIndexOf("\/");
+ if (newLocationLastSlash != -1)
+ relatedFilesDirStr = relatedFilesDirStr.slice(0, newLocationLastSlash);
+ if (oldLocation == relatedFilesDirStr || IsUrlAboutBlank(oldLocation))
+ relatedFilesDir = null;
+ else
+ relatedFilesDir = tempLocalFile.parent;
+ }
+ else
+ {
+ var lastSlash = urlstring.lastIndexOf("\/");
+ if (lastSlash != -1)
+ {
+ var relatedFilesDirString = urlstring.slice(0, lastSlash + 1); // include last slash
+ ioService = GetIOService();
+ relatedFilesDir = ioService.newURI(relatedFilesDirString, editor.documentCharacterSet, null);
+ }
+ }
+ } catch(e) { relatedFilesDir = null; }
+ }
+
+ var destinationLocation;
+ if (tempLocalFile)
+ destinationLocation = tempLocalFile;
+ else
+ destinationLocation = docURI;
+
+ success = OutputFileWithPersistAPI(editorDoc, destinationLocation, relatedFilesDir, aMimeType);
+ }
+ catch (e)
+ {
+ success = false;
+ }
+
+ if (success)
+ {
+ try {
+ if (doUpdateURI)
+ {
+ // If a local file, we must create a new uri from nsILocalFile
+ if (tempLocalFile)
+ docURI = GetFileProtocolHandler().newFileURI(tempLocalFile);
+
+ // We need to set new document uri before notifying listeners
+ SetDocumentURI(docURI);
+ }
+
+ // Update window title to show possibly different filename
+ // This also covers problem that after undoing a title change,
+ // window title loses the extra [filename] part that this adds
+ UpdateWindowTitle();
+
+ if (!aSaveCopy)
+ editor.resetModificationCount();
+ // this should cause notification to listeners that document has changed
+
+ // Set UI based on whether we're editing a remote or local url
+ SetSaveAndPublishUI(urlstring);
+ } catch (e) {}
+ }
+ else
+ {
+ var saveDocStr = GetString("SaveDocument");
+ var failedStr = GetString("SaveFileFailed");
+ AlertWithTitle(saveDocStr, failedStr);
+ }
+ return success;
+}
+
+function SetDocumentURI(uri)
+{
+ try {
+ // XXX WE'LL NEED TO GET "CURRENT" CONTENT FRAME ONCE MULTIPLE EDITORS ARE ALLOWED
+ GetCurrentEditorElement().docShell.setCurrentURI(uri);
+ } catch (e) { dump("SetDocumentURI:\n"+e +"\n"); }
+}
+
+
+//------------------------------- Publishing
+var gPublishData;
+var gProgressDialog;
+var gCommandAfterPublishing = null;
+var gRestoreDocumentSource;
+
+function Publish(publishData)
+{
+ if (!publishData)
+ return false;
+
+ // Set data in global for username password requests
+ // and to do "post saving" actions after monitoring nsIWebProgressListener messages
+ // and we are sure file transfer was successful
+ gPublishData = publishData;
+
+ gPublishData.docURI = CreateURIFromPublishData(publishData, true);
+ if (!gPublishData.docURI)
+ {
+ AlertWithTitle(GetString("Publish"), GetString("PublishFailed"));
+ return false;
+ }
+
+ if (gPublishData.publishOtherFiles)
+ gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
+ else
+ gPublishData.otherFilesURI = null;
+
+ if (gShowDebugOutputStateChange)
+ {
+ dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+
+ ", Username="+publishData.username+", Dir="+publishData.docDir+
+ ", Filename="+publishData.filename+"\n");
+ dump(" * gPublishData.docURI.spec w/o pass="+StripPassword(gPublishData.docURI.spec)+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
+ }
+
+ // XXX Missing username will make FTP fail
+ // and it won't call us for prompt dialog (bug 132320)
+ // (It does prompt if just password is missing)
+ // So we should do the prompt ourselves before trying to publish
+ if (GetScheme(publishData.publishUrl) == "ftp" && !publishData.username)
+ {
+ var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl));
+ var savePWobj = {value:publishData.savePassword};
+ var userObj = {value:publishData.username};
+ var pwObj = {value:publishData.password};
+ if (!PromptUsernameAndPassword(GetString("Prompt"), message, savePWobj, userObj, pwObj))
+ return false; // User canceled out of dialog
+
+ // Reset data in URI objects
+ gPublishData.docURI.username = publishData.username;
+ gPublishData.docURI.password = publishData.password;
+
+ if (gPublishData.otherFilesURI)
+ {
+ gPublishData.otherFilesURI.username = publishData.username;
+ gPublishData.otherFilesURI.password = publishData.password;
+ }
+ }
+
+ try {
+ // We launch dialog as a dependent
+ // Don't allow editing document!
+ SetDocumentEditable(false);
+
+ // Start progress monitoring
+ gProgressDialog =
+ window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank",
+ "chrome,dependent,titlebar", gPublishData, gPersistObj);
+
+ } catch (e) {}
+
+ // Network transfer is often too quick for the progress dialog to be initialized
+ // and we can completely miss messages for quickly-terminated bad URLs,
+ // so we can't call OutputFileWithPersistAPI right away.
+ // StartPublishing() is called at the end of the dialog's onload method
+ return true;
+}
+
+function StartPublishing()
+{
+ var editor = GetCurrentEditor();
+ if (editor && gPublishData && gPublishData.docURI && gProgressDialog)
+ {
+ gRestoreDocumentSource = null;
+
+ // Save backup document since nsIWebBrowserPersist changes image src urls
+ // but we only need to do this if publishing images and other related files
+ if (gPublishData.otherFilesURI)
+ {
+ try {
+ gRestoreDocumentSource =
+ editor.outputToString(editor.contentsMIMEType, kOutputEncodeW3CEntities);
+ } catch (e) {}
+ }
+
+ OutputFileWithPersistAPI(editor.document,
+ gPublishData.docURI, gPublishData.otherFilesURI,
+ editor.contentsMIMEType);
+ return gPersistObj;
+ }
+ return null;
+}
+
+function CancelPublishing()
+{
+ try {
+ gPersistObj.cancelSave();
+ gProgressDialog.SetProgressStatusCancel();
+ } catch (e) {}
+
+ // If canceling publishing do not do any commands after this
+ gCommandAfterPublishing = null;
+
+ if (gProgressDialog)
+ {
+ // Close Progress dialog
+ // (this will call FinishPublishing())
+ gProgressDialog.CloseDialog();
+ }
+ else
+ FinishPublishing();
+}
+
+function FinishPublishing()
+{
+ SetDocumentEditable(true);
+ gProgressDialog = null;
+ gPublishData = null;
+ gRestoreDocumentSource = null;
+
+ if (gCommandAfterPublishing)
+ {
+ // Be sure to null out the global now incase of trouble when executing command
+ var command = gCommandAfterPublishing;
+ gCommandAfterPublishing = null;
+ goDoCommand(command);
+ }
+}
+
+// Create a nsIURI object filled in with all required publishing info
+function CreateURIFromPublishData(publishData, doDocUri)
+{
+ if (!publishData || !publishData.publishUrl)
+ return null;
+
+ var URI;
+ try {
+ var spec = publishData.publishUrl;
+ if (doDocUri)
+ spec += FormatDirForPublishing(publishData.docDir) + publishData.filename;
+ else
+ spec += FormatDirForPublishing(publishData.otherDir);
+
+ var ioService = GetIOService();
+ URI = ioService.newURI(spec, GetCurrentEditor().documentCharacterSet, null);
+
+ if (publishData.username)
+ URI.username = publishData.username;
+ if (publishData.password)
+ URI.password = publishData.password;
+ }
+ catch (e) {}
+
+ return URI;
+}
+
+// Resolve the correct "http:" document URL when publishing via ftp
+function GetDocUrlFromPublishData(publishData)
+{
+ if (!publishData || !publishData.filename || !publishData.publishUrl)
+ return "";
+
+ // If user was previously editing an "ftp" url, then keep that as the new scheme
+ var url;
+ var docScheme = GetScheme(GetDocumentUrl());
+
+ // Always use the "HTTP" address if available
+ // XXX Should we do some more validation here for bad urls???
+ // Let's at least check for a scheme!
+ if (!GetScheme(publishData.browseUrl))
+ url = publishData.publishUrl;
+ else
+ url = publishData.browseUrl;
+
+ url += FormatDirForPublishing(publishData.docDir) + publishData.filename;
+
+ if (GetScheme(url) == "ftp")
+ url = InsertUsernameIntoUrl(url, publishData.username);
+
+ return url;
+}
+
+function SetSaveAndPublishUI(urlstring)
+{
+ // Be sure enabled state of toolbar buttons are correct
+ goUpdateCommand("cmd_save");
+ goUpdateCommand("cmd_publish");
+}
+
+function SetDocumentEditable(isDocEditable)
+{
+ var editor = GetCurrentEditor();
+ if (editor && editor.document)
+ {
+ try {
+ var flags = editor.flags;
+ editor.flags = isDocEditable ?
+ flags &= ~nsIPlaintextEditor.eEditorReadonlyMask :
+ flags | nsIPlaintextEditor.eEditorReadonlyMask;
+ } catch(e) {}
+
+ // update all commands
+ window.updateCommands("create");
+ }
+}
+
+// ****** end of save / publish **********//
+
+//-----------------------------------------------------------------------------------
+var nsPublishSettingsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (GetCurrentEditor())
+ {
+ // Launch Publish Settings dialog
+
+ window.ok = window.openDialog("chrome://editor/content/EditorPublishSettings.xul","_blank", "chrome,close,titlebar,modal", "");
+ window.content.focus();
+ return window.ok;
+ }
+ return false;
+ }
+}
+
+//-----------------------------------------------------------------------------------
+var nsRevertCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() &&
+ IsDocumentModified() &&
+ !IsUrlAboutBlank(GetDocumentUrl()));
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Confirm with the user to abandon current changes
+ var promptService = GetPromptService();
+ if (promptService)
+ {
+ // Put the page title in the message string
+ var title = GetDocumentTitle();
+ if (!title)
+ title = GetString("untitled");
+
+ var msg = GetString("AbandonChanges").replace(/%title%/,title);
+
+ var result = promptService.confirmEx(window, GetString("RevertCaption"), msg,
+ (promptService.BUTTON_TITLE_REVERT * promptService.BUTTON_POS_0) +
+ (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
+ null, null, null, null, {value:0});
+
+ // Reload page if first button (Revert) was pressed
+ if(result == 0)
+ {
+ CancelHTMLSource();
+ EditorLoadUrl(GetDocumentUrl());
+ }
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsCloseCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return GetCurrentEditor() != null;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ CloseWindow();
+ }
+};
+
+function CloseWindow()
+{
+ // Check to make sure document is saved. "true" means allow "Don't Save" button,
+ // so user can choose to close without saving
+ if (CheckAndSaveDocument("cmd_close", true))
+ {
+ if (window.InsertCharWindow)
+ SwitchInsertCharToAnotherEditorOrClose();
+
+ try {
+ var basewin = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+ .treeOwner
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIBaseWindow);
+ basewin.destroy();
+ } catch (e) {}
+ }
+}
+
+//-----------------------------------------------------------------------------------
+var nsOpenRemoteCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true; // we can always do this
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var params = { browser: null, action: null, url: "" };
+ openDialog( "chrome://communicator/content/openLocation.xul", "_blank", "chrome,modal,titlebar", params);
+ var win = getTopWin();
+ switch (params.action) {
+ case "0": // current window
+ win.focus();
+ win.loadURI(params.url, null,
+ nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
+ break;
+ case "1": // new window
+ openDialog(getBrowserURL(), "_blank", "all,dialog=no", params.url, null,
+ null, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
+ break;
+ case "2": // edit
+ editPage(params.url);
+ break;
+ case "3": // new tab
+ win.focus();
+ var browser = win.getBrowser();
+ browser.selectedTab = browser.addTab(params.url, null, null, false,
+ nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
+ break;
+ default:
+ window.content.focus();
+ break;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsPreviewCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() &&
+ IsHTMLEditor() &&
+ (DocumentHasBeenSaved() || IsDocumentModified()));
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Don't continue if user canceled during prompt for saving
+ // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
+ if (!CheckAndSaveDocument("cmd_preview", DocumentHasBeenSaved()))
+ return;
+
+ // Check if we saved again just in case?
+ if (DocumentHasBeenSaved())
+ {
+ var browser;
+ try {
+ // Find a browser with this URL
+ var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
+ var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
+ var enumerator = windowManagerInterface.getEnumerator("navigator:browser");
+
+ var documentURI = GetDocumentUrl();
+ while ( enumerator.hasMoreElements() )
+ {
+ browser = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindowInternal);
+ if ( browser && (documentURI == browser.getBrowser().currentURI.spec))
+ break;
+
+ browser = null;
+ }
+ }
+ catch (ex) {}
+
+ // If none found, open a new browser
+ if (!browser)
+ {
+ browser = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", documentURI);
+ }
+ else
+ {
+ try {
+ browser.BrowserReloadSkipCache();
+ browser.focus();
+ } catch (ex) {}
+ }
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsSendPageCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() &&
+ (DocumentHasBeenSaved() || IsDocumentModified()));
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Don't continue if user canceled during prompt for saving
+ // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
+ if (!CheckAndSaveDocument("cmd_editSendPage", DocumentHasBeenSaved()))
+ return;
+
+ // Check if we saved again just in case?
+ if (DocumentHasBeenSaved())
+ {
+ // Launch Messenger Composer window with current page as contents
+ try
+ {
+ openComposeWindow(GetDocumentUrl(), GetDocumentTitle());
+ } catch (ex) { dump("Cannot Send Page: " + ex + "\n"); }
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsPrintCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true; // we can always do this
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // In editor.js
+ FinishHTMLSource();
+ try {
+ PrintUtils.print();
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsPrintSetupCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true; // we can always do this
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // In editor.js
+ FinishHTMLSource();
+ PrintUtils.showPageSetup();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsQuitCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true; // we can always do this
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {}
+
+ /* The doCommand is not used, since cmd_quit's oncommand="goQuitApplication()" in platformCommunicatorOverlay.xul
+ doCommand: function(aCommand)
+ {
+ // In editor.js
+ FinishHTMLSource();
+ goQuitApplication();
+ }
+ */
+};
+
+//-----------------------------------------------------------------------------------
+var nsFindCommand =
+{
+ isCommandEnabled: function(aCommand, editorElement)
+ {
+ return editorElement.getEditor(editorElement.contentWindow) != null;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, editorElement) {},
+ doCommandParams: function(aCommand, aParams, editorElement) {},
+
+ doCommand: function(aCommand, editorElement)
+ {
+ try {
+ window.openDialog("chrome://editor/content/EdReplace.xul", "_blank",
+ "chrome,modal,titlebar", editorElement);
+ }
+ catch(ex) {
+ dump("*** Exception: couldn't open Replace Dialog\n");
+ }
+ //window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsFindAgainCommand =
+{
+ isCommandEnabled: function(aCommand, editorElement)
+ {
+ // we can only do this if the search pattern is non-empty. Not sure how
+ // to get that from here
+ return editorElement.getEditor(editorElement.contentWindow) != null;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, editorElement) {},
+ doCommandParams: function(aCommand, aParams, editorElement) {},
+
+ doCommand: function(aCommand, editorElement)
+ {
+ try {
+ var findPrev = aCommand == "cmd_findPrev";
+ var findInst = editorElement.webBrowserFind;
+ var findService = Components.classes["@mozilla.org/find/find_service;1"]
+ .getService(Components.interfaces.nsIFindService);
+ findInst.findBackwards = findService.findBackwards ^ findPrev;
+ findInst.findNext();
+ // reset to what it was in dialog, otherwise dialog setting can get reversed
+ findInst.findBackwards = findService.findBackwards;
+ }
+ catch (ex) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsRewrapCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && !IsInHTMLSourceMode() &&
+ GetCurrentEditor() instanceof Components.interfaces.nsIEditorMailSupport);
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorMailSupport).rewrap(false);
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsSpellingCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() &&
+ !IsInHTMLSourceMode() && IsSpellCheckerInstalled());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.cancelSendMessage = false;
+ try {
+ var skipBlockQuotes = (window.document.documentElement.getAttribute("windowtype") == "msgcompose");
+ window.openDialog("chrome://editor/content/EdSpellCheck.xul", "_blank",
+ "chrome,close,titlebar,modal", false, skipBlockQuotes, true);
+ }
+ catch(ex) {}
+ window.content.focus();
+ }
+};
+
+// Validate using http://validator.w3.org/file-upload.html
+var URL2Validate;
+var nsValidateCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return GetCurrentEditor() != null;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // If the document hasn't been modified,
+ // then just validate the current url.
+ if (IsDocumentModified() || IsHTMLSourceChanged())
+ {
+ if (!CheckAndSaveDocument("cmd_validate", false))
+ return;
+
+ // Check if we saved again just in case?
+ if (!DocumentHasBeenSaved()) // user hit cancel?
+ return;
+ }
+
+ URL2Validate = GetDocumentUrl();
+ // See if it's a file:
+ var ifile;
+ try {
+ var fileHandler = GetFileProtocolHandler();
+ ifile = fileHandler.getFileFromURLSpec(URL2Validate);
+ // nsIFile throws an exception if it's not a file url
+ } catch (e) { ifile = null; }
+ if (ifile)
+ {
+ URL2Validate = ifile.path;
+ var vwin = window.open("http://validator.w3.org/file-upload.html",
+ "EditorValidate");
+ // Window loads asynchronously, so pass control to the load listener:
+ vwin.addEventListener("load", this.validateFilePageLoaded, false);
+ }
+ else
+ {
+ var vwin2 = window.open("http://validator.w3.org/check?uri="
+ + URL2Validate
+ + "&doctype=Inline",
+ "EditorValidate");
+ // This does the validation, no need to wait for page loaded.
+ }
+ },
+ validateFilePageLoaded: function(event)
+ {
+ event.target.forms[0].uploaded_file.value = URL2Validate;
+ }
+};
+
+var nsCheckLinksCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdLinkChecker.xul","_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsFormCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdFormProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInputTagCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdInputProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInputImageCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdInputImage.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsTextAreaCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdTextAreaProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsSelectCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdSelectProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsButtonCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdButtonProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsLabelCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var tagName = "label";
+ try {
+ var editor = GetCurrentEditor();
+ // Find selected label or if start/end of selection is in label
+ var labelElement = editor.getSelectedElement(tagName);
+ if (!labelElement)
+ labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.anchorNode);
+ if (!labelElement)
+ labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.focusNode);
+ if (labelElement) {
+ // We only open the dialog for an existing label
+ window.openDialog("chrome://editor/content/EdLabelProps.xul", "_blank", "chrome,close,titlebar,modal", labelElement);
+ window.content.focus();
+ } else {
+ EditorSetTextProperty(tagName, "", "");
+ }
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsFieldSetCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdFieldSetProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsIsIndexCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ var editor = GetCurrentEditor();
+ var isindexElement = editor.createElementWithDefaults("isindex");
+ isindexElement.setAttribute("prompt", editor.outputToString("text/plain", kOutputSelectionOnly));
+ editor.insertElementAtSelection(isindexElement, true);
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsImageCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsHLineCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Inserting an HLine is different in that we don't use properties dialog
+ // unless we are editing an existing line's attributes
+ // We get the last-used attributes from the prefs and insert immediately
+
+ var tagName = "hr";
+ var editor = GetCurrentEditor();
+
+ var hLine;
+ try {
+ hLine = editor.getSelectedElement(tagName);
+ } catch (e) {return;}
+
+ if (hLine)
+ {
+ // We only open the dialog for an existing HRule
+ window.openDialog("chrome://editor/content/EdHLineProps.xul", "_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+ else
+ {
+ try {
+ hLine = editor.createElementWithDefaults(tagName);
+
+ // We change the default attributes to those saved in the user prefs
+ var prefs = GetPrefs();
+ var align = prefs.getIntPref("editor.hrule.align");
+ if (align == 0)
+ editor.setAttributeOrEquivalent(hLine, "align", "left", true);
+ else if (align == 2)
+ editor.setAttributeOrEquivalent(hLine, "align", "right", true);
+
+ //Note: Default is center (don't write attribute)
+
+ var width = prefs.getIntPref("editor.hrule.width");
+ var percent = prefs.getBoolPref("editor.hrule.width_percent");
+ if (percent)
+ width = width +"%";
+
+ editor.setAttributeOrEquivalent(hLine, "width", width, true);
+
+ var height = prefs.getIntPref("editor.hrule.height");
+ editor.setAttributeOrEquivalent(hLine, "size", String(height), true);
+
+ var shading = prefs.getBoolPref("editor.hrule.shading");
+ if (shading)
+ hLine.removeAttribute("noshade");
+ else
+ hLine.setAttribute("noshade", "noshade");
+
+ editor.insertElementAtSelection(hLine, true);
+
+ } catch (e) {}
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsLinkCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // If selected element is an image, launch that dialog instead
+ // since last tab panel handles link around an image
+ var element = GetObjectForProperties();
+ if (element && element.nodeName.toLowerCase() == "img")
+ window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal", null, true);
+ else
+ window.openDialog("chrome://editor/content/EdLinkProps.xul","_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsAnchorCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdNamedAnchorProps.xul", "_blank", "chrome,close,titlebar,modal", "");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertHTMLWithDialogCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdInsSrc.xul","_blank", "chrome,close,titlebar,modal,resizable", "");
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertCharsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ EditorFindOrCreateInsertCharWindow();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertBreakCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentEditor().insertHTML("<br>");
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertBreakAllCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentEditor().insertHTML("<br clear='all'>");
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsGridCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdSnapToGrid.xul","_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsListPropertiesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdListProps.xul","_blank", "chrome,close,titlebar,modal");
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsPagePropertiesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var oldTitle = GetDocumentTitle();
+ window.openDialog("chrome://editor/content/EdPageProps.xul","_blank", "chrome,close,titlebar,modal", "");
+
+ // Update main window title and
+ // recent menu data in prefs if doc title changed
+ if (GetDocumentTitle() != oldTitle)
+ UpdateWindowTitle();
+
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsObjectPropertiesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ var isEnabled = false;
+ if (IsDocumentEditable() && IsEditingRenderedHTML())
+ {
+ isEnabled = (GetObjectForProperties() != null ||
+ GetCurrentEditor().getSelectedElement("href") != null);
+ }
+ return isEnabled;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Launch Object properties for appropriate selected element
+ var element = GetObjectForProperties();
+ if (element)
+ {
+ var name = element.nodeName.toLowerCase();
+ switch (name)
+ {
+ case 'img':
+ goDoCommand("cmd_image");
+ break;
+ case 'hr':
+ goDoCommand("cmd_hline");
+ break;
+ case 'form':
+ goDoCommand("cmd_form");
+ break;
+ case 'input':
+ var type = element.getAttribute("type");
+ if (type && type.toLowerCase() == "image")
+ goDoCommand("cmd_inputimage");
+ else
+ goDoCommand("cmd_inputtag");
+ break;
+ case 'textarea':
+ goDoCommand("cmd_textarea");
+ break;
+ case 'select':
+ goDoCommand("cmd_select");
+ break;
+ case 'button':
+ goDoCommand("cmd_button");
+ break;
+ case 'label':
+ goDoCommand("cmd_label");
+ break;
+ case 'fieldset':
+ goDoCommand("cmd_fieldset");
+ break;
+ case 'table':
+ EditorInsertOrEditTable(false);
+ break;
+ case 'td':
+ case 'th':
+ EditorTableCellProperties();
+ break;
+ case 'ol':
+ case 'ul':
+ case 'dl':
+ case 'li':
+ goDoCommand("cmd_listProperties");
+ break;
+ case 'a':
+ if (element.name)
+ {
+ goDoCommand("cmd_anchor");
+ }
+ else if(element.href)
+ {
+ goDoCommand("cmd_link");
+ }
+ break;
+ default:
+ doAdvancedProperties(element);
+ break;
+ }
+ } else {
+ // We get a partially-selected link if asked for specifically
+ try {
+ element = GetCurrentEditor().getSelectedElement("href");
+ } catch (e) {}
+ if (element)
+ goDoCommand("cmd_link");
+ }
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsSetSmiley =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon)
+ {
+ var smileyCode = aParams.getStringValue("state_attribute");
+
+ var strSml;
+ switch(smileyCode)
+ {
+ case ":-)": strSml="s1";
+ break;
+ case ":-(": strSml="s2";
+ break;
+ case ";-)": strSml="s3";
+ break;
+ case ":-P":
+ case ":-p":
+ case ":-b": strSml="s4";
+ break;
+ case ":-D": strSml="s5";
+ break;
+ case ":-[": strSml="s6";
+ break;
+ case ":-/":
+ case ":/":
+ case ":-\\":
+ case ":\\": strSml="s7";
+ break;
+ case "=-O":
+ case "=-o": strSml="s8";
+ break;
+ case ":-*": strSml="s9";
+ break;
+ case ">:o":
+ case ">:-o": strSml="s10";
+ break;
+ case "8-)": strSml="s11";
+ break;
+ case ":-$": strSml="s12";
+ break;
+ case ":-!": strSml="s13";
+ break;
+ case "O:-)":
+ case "o:-)": strSml="s14";
+ break;
+ case ":'(": strSml="s15";
+ break;
+ case ":-X":
+ case ":-x": strSml="s16";
+ break;
+ default: strSml="";
+ break;
+ }
+
+ try
+ {
+ var editor = GetCurrentEditor();
+ var selection = editor.selection;
+ var extElement = editor.createElementWithDefaults("span");
+ extElement.setAttribute("class", "moz-smiley-" + strSml);
+
+ var intElement = editor.createElementWithDefaults("span");
+ if (!intElement)
+ return;
+
+ //just for mailnews, because of the way it removes HTML
+ var smileButMenu = document.getElementById('smileButtonMenu');
+ if (smileButMenu.getAttribute("padwithspace"))
+ smileyCode = " " + smileyCode + " ";
+
+ var txtElement = editor.document.createTextNode(smileyCode);
+ if (!txtElement)
+ return;
+
+ intElement.appendChild (txtElement);
+ extElement.appendChild (intElement);
+
+
+ editor.insertElementAtSelection(extElement,true);
+ window.content.focus();
+
+ }
+ catch (e)
+ {
+ dump("Exception occured in smiley InsertElementAtSelection\n");
+ }
+ },
+ // This is now deprecated in favor of "doCommandParams"
+ doCommand: function(aCommand) {}
+};
+
+
+function doAdvancedProperties(element)
+{
+ if (element)
+ {
+ window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank", "chrome,close,titlebar,modal,resizable=yes", "", element);
+ window.content.focus();
+ }
+}
+
+var nsAdvancedPropertiesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Launch AdvancedEdit dialog for the selected element
+ try {
+ var element = GetCurrentEditor().getSelectedElement("");
+ doAdvancedProperties(element);
+ } catch (e) {}
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsColorPropertiesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ window.openDialog("chrome://editor/content/EdColorProps.xul","_blank", "chrome,close,titlebar,modal", "");
+ UpdateDefaultColors();
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsRemoveNamedAnchorsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ // We could see if there's any link in selection, but it doesn't seem worth the work!
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ EditorRemoveTextProperty("name", "");
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsEditLinkCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ // Not really used -- this command is only in context menu, and we do enabling there
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ var element = GetCurrentEditor().getSelectedElement("href");
+ if (element)
+ editPage(element.href, window, false);
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsNormalModeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsHTMLEditor() && IsDocumentEditable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ SetEditMode(kDisplayModeNormal);
+ }
+};
+
+var nsAllTagsModeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsHTMLEditor());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ SetEditMode(kDisplayModeAllTags);
+ }
+};
+
+var nsHTMLSourceModeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsHTMLEditor());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ SetEditMode(kDisplayModeSource);
+ }
+};
+
+var nsPreviewModeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsHTMLEditor());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ SetEditMode(kDisplayModePreview);
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertOrEditTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return (IsDocumentEditable() && IsEditingRenderedHTML());
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (IsInTableCell())
+ EditorTableCellProperties();
+ else
+ EditorInsertOrEditTable(true);
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsEditTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ EditorInsertOrEditTable(false);
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsSelectTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().selectTable();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsSelectTableRowCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().selectTableRow();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsSelectTableColumnCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().selectTableColumn();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsSelectTableCellCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().selectTableCell();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsSelectAllTableCellsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().selectAllTableCells();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsInsertTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsDocumentEditable() && IsEditingRenderedHTML();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ EditorInsertTable();
+ }
+};
+
+var nsInsertTableRowAboveCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableRow(1, false);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsInsertTableRowBelowCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableRow(1, true);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsInsertTableColumnBeforeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableColumn(1, false);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsInsertTableColumnAfterCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableColumn(1, true);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsInsertTableCellBeforeCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableCell(1, false);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsInsertTableCellAfterCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().insertTableCell(1, true);
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsDeleteTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().deleteTable();
+ } catch(e) {}
+ window.content.focus();
+ }
+};
+
+var nsDeleteTableRowCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var rows = GetNumberOfContiguousSelectedRows();
+ // Delete at least one row
+ if (rows == 0)
+ rows = 1;
+
+ try {
+ var editor = GetCurrentTableEditor();
+ editor.beginTransaction();
+
+ // Loop to delete all blocks of contiguous, selected rows
+ while (rows)
+ {
+ editor.deleteTableRow(rows);
+ rows = GetNumberOfContiguousSelectedRows();
+ }
+ } finally { editor.endTransaction(); }
+ window.content.focus();
+ }
+};
+
+var nsDeleteTableColumnCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ var columns = GetNumberOfContiguousSelectedColumns();
+ // Delete at least one column
+ if (columns == 0)
+ columns = 1;
+
+ try {
+ var editor = GetCurrentTableEditor();
+ editor.beginTransaction();
+
+ // Loop to delete all blocks of contiguous, selected columns
+ while (columns)
+ {
+ editor.deleteTableColumn(columns);
+ columns = GetNumberOfContiguousSelectedColumns();
+ }
+ } finally { editor.endTransaction(); }
+ window.content.focus();
+ }
+};
+
+var nsDeleteTableCellCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().deleteTableCell(1);
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+var nsDeleteTableCellContentsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTableCell();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().deleteTableCellContents();
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+var nsNormalizeTableCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Use nsnull to let editor find table enclosing current selection
+ try {
+ GetCurrentTableEditor().normalizeTable(null);
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsJoinTableCellsCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ if (IsDocumentEditable() && IsEditingRenderedHTML())
+ {
+ try {
+ var editor = GetCurrentTableEditor();
+ var tagNameObj = { value: "" };
+ var countObj = { value: 0 };
+ var cell = editor.getSelectedOrParentTableElement(tagNameObj, countObj);
+
+ // We need a cell and either > 1 selected cell or a cell to the right
+ // (this cell may originate in a row spanned from above current row)
+ // Note that editor returns "td" for "th" also.
+ // (this is a pain! Editor and gecko use lowercase tagNames, JS uses uppercase!)
+ if( cell && (tagNameObj.value == "td"))
+ {
+ // Selected cells
+ if (countObj.value > 1) return true;
+
+ var colSpan = cell.getAttribute("colspan");
+
+ // getAttribute returns string, we need number
+ // no attribute means colspan = 1
+ if (!colSpan)
+ colSpan = Number(1);
+ else
+ colSpan = Number(colSpan);
+
+ var rowObj = { value: 0 };
+ var colObj = { value: 0 };
+ editor.getCellIndexes(cell, rowObj, colObj);
+
+ // Test if cell exists to the right of current cell
+ // (cells with 0 span should never have cells to the right
+ // if there is, user can select the 2 cells to join them)
+ return (colSpan && editor.getCellAt(null, rowObj.value,
+ colObj.value + colSpan));
+ }
+ } catch (e) {}
+ }
+ return false;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // Param: Don't merge non-contiguous cells
+ try {
+ GetCurrentTableEditor().joinTableCells(false);
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsSplitTableCellCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ if (IsDocumentEditable() && IsEditingRenderedHTML())
+ {
+ var tagNameObj = { value: "" };
+ var countObj = { value: 0 };
+ var cell;
+ try {
+ cell = GetCurrentTableEditor().getSelectedOrParentTableElement(tagNameObj, countObj);
+ } catch (e) {}
+
+ // We need a cell parent and there's just 1 selected cell
+ // or selection is entirely inside 1 cell
+ if ( cell && (tagNameObj.value == "td") &&
+ countObj.value <= 1 &&
+ IsSelectionInOneCell() )
+ {
+ var colSpan = cell.getAttribute("colspan");
+ var rowSpan = cell.getAttribute("rowspan");
+ if (!colSpan) colSpan = 1;
+ if (!rowSpan) rowSpan = 1;
+ return (colSpan > 1 || rowSpan > 1 ||
+ colSpan == 0 || rowSpan == 0);
+ }
+ }
+ return false;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ try {
+ GetCurrentTableEditor().splitTableCell();
+ } catch (e) {}
+ window.content.focus();
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsTableOrCellColorCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return IsInTable();
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ EditorSelectColor("TableOrCell");
+ }
+};
+
+//-----------------------------------------------------------------------------------
+var nsPreferencesCommand =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ goPreferences('composer_pane');
+ window.content.focus();
+ }
+};
+
+
+var nsFinishHTMLSource =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // In editor.js
+ FinishHTMLSource();
+ }
+};
+
+var nsCancelHTMLSource =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ return true;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ // In editor.js
+ CancelHTMLSource();
+ }
+};
+
+var nsConvertToTable =
+{
+ isCommandEnabled: function(aCommand, dummy)
+ {
+ if (IsDocumentEditable() && IsEditingRenderedHTML())
+ {
+ var selection;
+ try {
+ selection = GetCurrentEditor().selection;
+ } catch (e) {}
+
+ if (selection && !selection.isCollapsed)
+ {
+ // Don't allow if table or cell is the selection
+ var element;
+ try {
+ element = GetCurrentEditor().getSelectedElement("");
+ } catch (e) {}
+ if (element)
+ {
+ var name = element.nodeName.toLowerCase();
+ if (name == "td" ||
+ name == "th" ||
+ name == "caption" ||
+ name == "table")
+ return false;
+ }
+
+ // Selection start and end must be in the same cell
+ // in same cell or both are NOT in a cell
+ if ( GetParentTableCell(selection.focusNode) !=
+ GetParentTableCell(selection.anchorNode) )
+ return false
+
+ return true;
+ }
+ }
+ return false;
+ },
+
+ getCommandStateParams: function(aCommand, aParams, aRefCon) {},
+ doCommandParams: function(aCommand, aParams, aRefCon) {},
+
+ doCommand: function(aCommand)
+ {
+ if (this.isCommandEnabled())
+ {
+ window.openDialog("chrome://editor/content/EdConvertToTable.xul","_blank", "chrome,close,titlebar,modal")
+ }
+ window.content.focus();
+ }
+};
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/EditorAllTags.css
@@ -0,0 +1,835 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Styles to alter look of things in the Editor content window
+ * for the "All Tags Edit Mode" Every HTML tag shows up as an icon.
+*/
+
+/* For "userdefined" or "unknown" tags
+ (Note that "_" must be escaped)
+*/
+
+*:not(a):not(abbr):not(acronym):not(address):not(applet):not(area):not(b):not(base):not(basefont):not(bdo):not(bgsound):not(big):not(blink):not(blockquote):not(body):not(br):not(button):not(canvas):not(caption):not(center):not(cite):not(code):not(col):not(colgroup):not(dd):not(del):not(dfn):not(dir):not(div):not(dl):not(dt):not(em):not(embed):not(fieldset):not(font):not(form):not(frame):not(frameset):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(head):not(hr):not(html):not(i):not(iframe):not(image):not(img):not(input):not(ins):not(isindex):not(kbd):not(keygen):not(label):not(legend):not(li):not(link):not(listing):not(map):not(marquee):not(menu):not(meta):not(multicol):not(nobr):not(noembed):not(noframes):not(noscript):not(object):not(ol):not(optgroup):not(option):not(p):not(param):not(plaintext):not(pre):not(q):not(s):not(samp):not(script):not(select):not(server):not(small):not(sound):not(spacer):not(span):not(strike):not(strong):not(style):not(sub):not(sup):not(table):not(tbody):not(td):not(textarea):not(tfoot):not(th):not(thead):not(title):not(tr):not(tt):not(u):not(ul):not(var):not(wbr):not(xmp) {
+ display: inline;
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 16px;
+ background-image: url(chrome://editor/content/images/tag-userdefined.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+a:not([\_moz_anonclass]) {
+ min-height: 16px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-a.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+abbr {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 35px;
+ background-image: url(chrome://editor/content/images/tag-abr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+
+acronym {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 57px;
+ background-image: url(chrome://editor/content/images/tag-acr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+address {
+ min-height: 44px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-adr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+applet {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 47px;
+ background-image: url(chrome://editor/content/images/tag-app.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+area {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-ara.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+b {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-b.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+basefont {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 57px;
+ background-image: url(chrome://editor/content/images/tag-bsf.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+bdo {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-bdo.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+big {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-big.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+blockquote {
+ min-height: 44px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-blq.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+body {
+ min-height: 36px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-body.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+br {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-br.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+button {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 57px;
+ background-image: url(chrome://editor/content/images/tag-btn.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+caption {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 55px;
+ background-image: url(chrome://editor/content/images/tag-cpt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+center {
+ min-height: 44px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-ctr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+cite {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-cit.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+code {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-cod.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+col {
+ min-height: 35px; margin-left: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-col.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+colgroup {
+ min-height: 35px; margin-left: 2px;
+ padding-left: 51px;
+ background-image: url(chrome://editor/content/images/tag-clg.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+dd {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-dd.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+del {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-del.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+dfn {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-dfn.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+dir {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-dir.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+div {
+ min-height: 24px; margin-top: 2px;
+ /* TEMPORARY TO COMPENSATE FOR BUG */
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-div.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+input div {
+ min-height: 0px; margin-left: 0px; margin-top: 0px;
+ padding-left: 0px;
+ background-image: none;
+}
+
+dl {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-dl.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+dt {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-dt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+em {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-em.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+fieldset {
+ min-height: 44px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-fld.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+font {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-fnt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+form {
+ min-height: 36px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-for.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+frame {
+ min-height: 40px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-frm.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+frameset {
+ min-height: 44px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-fst.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h1 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h1.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h2 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h2.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h3 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h3.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h4 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h4.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h5 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h5.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+h6 {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-h6.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+hr {
+ min-height: 20px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-hr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+i {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-i.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+iframe {
+ min-height: 35px; margin-left: 2px;
+ padding-left: 47px;
+ background-image: url(chrome://editor/content/images/tag-ifr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+img:not([\_moz_anonclass]) {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-img.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+input {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-inp.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+ins {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-ins.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+isindex {
+ min-height: 40px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-isx.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+kbd {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-kbd.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+label {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-lbl.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+legend {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 49px;
+ background-image: url(chrome://editor/content/images/tag-lgn.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+li {
+ min-height: 35px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-li.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+listing {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 57px;
+ background-image: url(chrome://editor/content/images/tag-lst.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+map {
+ min-height: 35px; margin-left: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-map.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+menu {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-men.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+nobr {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-nbr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+noframes {
+ min-height: 44px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-nfr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+noscript {
+ min-height: 44px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-nsc.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+object {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 49px;
+ background-image: url(chrome://editor/content/images/tag-obj.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+ol {
+ min-height: 38px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-ol.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+optgroup {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 51px;
+ background-image: url(chrome://editor/content/images/tag-opg.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+option {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 47px;
+ background-image: url(chrome://editor/content/images/tag-opt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+p {
+ min-height: 38px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-p.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+param {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 43px;
+ background-image: url(chrome://editor/content/images/tag-prm.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+plaintext {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 57px;
+ background-image: url(chrome://editor/content/images/tag-pln.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+pre {
+ min-height: 24px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-pre.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+q {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-q.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+s {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-s.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+samp {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-smp.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+script {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 45px;
+ background-image: url(chrome://editor/content/images/tag-scr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+select {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 47px;
+ background-image: url(chrome://editor/content/images/tag-slc.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+small {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 41px;
+ background-image: url(chrome://editor/content/images/tag-sml.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+span:not([\_moz_anonclass]) {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ /* TEMPORARY TO COMPENSATE FOR BUG */
+ padding-left: 39px;
+ background-image: url(chrome://editor/content/images/tag-spn.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+strike {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 45px;
+ background-image: url(chrome://editor/content/images/tag-stk.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+strong {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 51px;
+ background-image: url(chrome://editor/content/images/tag-stn.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+sub {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-sub.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+sup {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-sup.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+/* The background image technique is not working for
+ some table elements. Trying the "before" strategy
+*/
+
+table {
+ min-height: 40px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-tbl.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+tbody {
+ min-height: 42px; margin-left: 2px; margin-top: 1px;
+ padding-left: 17px;
+ content: url(chrome://editor/content/images/tag-tbd.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+td {
+ min-height: 22px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-td.gif);
+
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+textarea {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 59px;
+ background-image: url(chrome://editor/content/images/tag-txt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+tfoot {
+ min-height: 42px; margin-left: 2px; margin-top: 1px;
+ padding-left: 17px;
+ content: url(chrome://editor/content/images/tag-tft.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+th {
+ min-height: 22px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-th.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+thead {
+ min-height: 42px; margin-left: 2px; margin-top: 1px;
+ padding-left: 17px;
+ content: url(chrome://editor/content/images/tag-thd.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+tr {
+ min-height: 22px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-tr.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+tt {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-tt.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+u {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 23px;
+ background-image: url(chrome://editor/content/images/tag-u.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+ul {
+ min-height: 20px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-ul.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+var {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-var.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+xmp {
+ min-height: 35px; margin-left: 2px; margin-top: 2px;
+ padding-left: 31px;
+ background-image: url(chrome://editor/content/images/tag-xmp.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+
+/* These are tags that we DON'T want to show icons for.
+ We have images for them in case we want to utilize them
+ for some other purpose than the "All Tags" editor mode
+
+html {
+ min-height: 36px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-html.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+head {
+ min-height: 36px; margin-left: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-hed.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+These are tags that are ONLY allowed as children of HEAD:
+
+title {
+ min-height: 40px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-ttl.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+base {
+ min-height: 36px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-bas.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+style {
+ min-height: 40px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-stl.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+meta {
+ min-height: 36px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-met.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+link {
+ min-height: 30px; margin-left: 2px; margin-top: 2px;
+ padding-left: 17px;
+ background-image: url(chrome://editor/content/images/tag-lnk.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+*/
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/EditorContent.css
@@ -0,0 +1,96 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Daniel Glazman <glazman@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Styles to alter look of things in the Editor content window
+ * for the "Normal Edit Mode" These settings will be removed
+ * when we display in completely WYSIWYG "Edit Preview" mode
+ * Anything that should never change, like cursors, should be
+ * place in EditorOverride.css, instead of here.
+*/
+
+@import url(chrome://communicator/skin/smileys.css);
+
+a[name] {
+ min-height: 17px; margin-left: 2px; margin-top: 2px;
+ padding-left: 20px;
+ background-image: url(chrome://editor/content/images/tag-anchor.gif);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+
+/* Force border display for empty cells
+ and tables with 0 border
+*/
+table {
+ empty-cells: show;
+}
+
+/* give a red dotted border to tables and cells with no border
+ otherwise they are invisible
+*/
+table[empty-cells],
+ table[border="0"],
+ /* next two selectors on line below for the case where tbody is omitted */
+ table[border="0"] > tr > td, table[border="0"] > tr > th,
+ table[border="0"] > thead > tr > td, table[border="0"] > tbody > tr > td, table[border="0"] > tfoot > tr > td,
+ table[border="0"] > thead > tr > th, table[border="0"] > tbody > tr > th, table[border="0"] > tfoot > tr > th,
+ table:not([border]),
+ /* next two selectors on line below for the case where tbody is omitted */
+ table:not([border]) > tr > td, table:not([border]) > tr > th,
+ table:not([border]) > thead > tr > td, table:not([border]) > tbody > tr > td, table:not([border]) > tfoot > tr > td,
+ table:not([border]) > thead > tr > th, table:not([border]) > tbody > tr > th, table:not([border]) > tfoot > tr > th
+{
+ border: 1px dotted red;
+}
+
+/* give a green dashed border to forms otherwise they are invisible
+*/
+form
+{
+ border: 2px dashed green;
+}
+/* give a green dotted border to labels otherwise they are invisible
+*/
+label
+{
+ border: 1px dotted green;
+}
+
+img {
+ -moz-force-broken-image-icon: 1;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/EditorContextMenu.js
@@ -0,0 +1,172 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function EditorFillContextMenu(event, contextMenuNode)
+{
+ if ( event.target != contextMenuNode )
+ return;
+
+ // Setup object property menuitem
+ var objectName = InitObjectPropertiesMenuitem("objectProperties_cm");
+ var isInLink = objectName == "href";
+
+ // Special case of an image inside a link
+ if (objectName == "img")
+ try {
+ isInLink = GetCurrentEditor().getElementOrParentByTagName("href", GetObjectForProperties());
+ } catch (e) {}
+
+ InitRemoveStylesMenuitems("removeStylesMenuitem_cm", "removeLinksMenuitem_cm", "removeNamedAnchorsMenuitem_cm");
+
+ var inCell = IsInTableCell();
+ // Set appropriate text for join cells command
+ InitJoinCellMenuitem("joinTableCells_cm");
+
+ // Update enable states for all table commands
+ goUpdateTableMenuItems(document.getElementById("composerTableMenuItems"));
+
+ // Loop through all children to hide disabled items
+ var children = contextMenuNode.childNodes;
+ if (children)
+ {
+ var count = children.length;
+ for (var i = 0; i < count; i++)
+ HideDisabledItem(children[i]);
+ }
+
+ // The above loop will always show all separators and the next two items
+ // Hide "Create Link" if in a link
+ ShowMenuItem("createLink_cm", !isInLink);
+
+ // Hide "Edit link in new Composer" unless in a link
+ ShowMenuItem("editLink_cm", isInLink);
+
+ // Remove separators if all items in immediate group above are hidden
+ // A bit complicated to account if multiple groups are completely hidden!
+ var haveUndo =
+ IsMenuItemShowing("menu_undo_cm") ||
+ IsMenuItemShowing("menu_redo_cm");
+
+ var haveEdit =
+ IsMenuItemShowing("menu_cut_cm") ||
+ IsMenuItemShowing("menu_copy_cm") ||
+ IsMenuItemShowing("menu_paste_cm") ||
+ IsMenuItemShowing("menu_pasteNoFormatting_cm") ||
+ IsMenuItemShowing("menu_delete_cm");
+
+ var haveStyle =
+ IsMenuItemShowing("removeStylesMenuitem_cm") ||
+ IsMenuItemShowing("createLink_cm") ||
+ IsMenuItemShowing("removeLinksMenuitem_cm") ||
+ IsMenuItemShowing("removeNamedAnchorsMenuitem_cm");
+
+ var haveProps =
+ IsMenuItemShowing("objectProperties_cm");
+
+ ShowMenuItem("undoredo-separator", haveUndo && haveEdit);
+
+ ShowMenuItem("edit-separator", haveEdit || haveUndo);
+
+ // Note: Item "menu_selectAll_cm" and
+ // following separator are ALWAYS enabled,
+ // so there will always be 1 separator here
+
+ var showStyleSep = haveStyle && (haveProps || inCell);
+ ShowMenuItem("styles-separator", showStyleSep);
+
+ var showPropSep = (haveProps && inCell);
+ ShowMenuItem("property-separator", showPropSep);
+
+ // Remove table submenus if not in table
+ ShowMenuItem("tableInsertMenu_cm", inCell);
+ ShowMenuItem("tableSelectMenu_cm", inCell);
+ ShowMenuItem("tableDeleteMenu_cm", inCell);
+
+ // if we have a mispelled word, show spellchecker context
+ // menuitems as well as the usual context menu
+ InlineSpellCheckerUI.clearSuggestionsFromMenu();
+ InlineSpellCheckerUI.initFromEvent(document.popupRangeParent, document.popupRangeOffset);
+ var onMisspelling = InlineSpellCheckerUI.overMisspelling;
+ document.getElementById('spellCheckSuggestionsSeparator').hidden = !onMisspelling;
+ document.getElementById('spellCheckAddToDictionary').hidden = !onMisspelling;
+ document.getElementById('spellCheckIgnoreWord').hidden = !onMisspelling;
+ var separator = document.getElementById('spellCheckAddSep');
+ separator.hidden = !onMisspelling;
+ document.getElementById('spellCheckNoSuggestions').hidden = !onMisspelling ||
+ InlineSpellCheckerUI.addSuggestionsToMenu(contextMenuNode, separator, 5);
+}
+
+function IsItemOrCommandEnabled( item )
+{
+ var command = item.getAttribute("command");
+ if (command) {
+ // If possible, query the command controller directly
+ var controller = document.commandDispatcher.getControllerForCommand(command);
+ if (controller)
+ return controller.isCommandEnabled(command);
+ }
+
+ // Fall back on the inefficient observed disabled attribute
+ return item.getAttribute("disabled") != "true";
+}
+
+function HideDisabledItem( item )
+{
+ item.hidden = !IsItemOrCommandEnabled(item);
+}
+
+function ShowMenuItem(id, showItem)
+{
+ var item = document.getElementById(id);
+ if (item && !showItem)
+ {
+ item.hidden = true;
+ }
+ // else HideDisabledItem showed the item anyway
+}
+
+function IsMenuItemShowing(menuID)
+{
+ var item = document.getElementById(menuID);
+ if (item)
+ return !item.hidden;
+
+ return false;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/EditorContextMenuOverlay.xul
@@ -0,0 +1,164 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Daniel Glazman (glazman@netscape.com)
+ - Charles Manske (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/editorOverlay.dtd">
+
+<overlay id="ComposerContextMenuOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/x-javascript" src="chrome://editor/content/EditorContextMenu.js"/>
+<script type="application/x-javascript" src="chrome://editor/content/StructBarContextMenu.js"/>
+<script type="application/x-javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
+
+<popupset id="editorContentContextSet">
+ <popup id="editorContentContext"
+ onpopupshowing="EditorFillContextMenu(event, this);">
+ <menuitem id="spellCheckNoSuggestions" label="&spellCheckNoSuggestions.label;" disabled="true"/>
+ <menuseparator id="spellCheckAddSep"/>
+ <menuitem id="spellCheckAddToDictionary"
+ label="&spellCheckAddToDictionary.label;"
+ accesskey="&spellCheckAddToDictionary.accesskey;"
+ oncommand="InlineSpellCheckerUI.addToDictionary();"/>
+ <menuitem id="spellCheckIgnoreWord"
+ label="&spellCheckIgnoreWord.label;"
+ accesskey="&spellCheckIgnoreWord.accesskey;"
+ oncommand="InlineSpellCheckerUI.ignoreWord();"/>
+ <menuseparator id="spellCheckSuggestionsSeparator"/>
+
+ <menuitem id="menu_undo_cm" label="&undoCmd.label;" accesskey="&undo.accesskey;" command="cmd_undo"/>
+ <menuitem id="menu_redo_cm" label="&redoCmd.label;" accesskey="&redo.accesskey;" command="cmd_redo"/>
+ <menuseparator id="undoredo-separator"/>
+
+ <menuitem id="menu_cut_cm" label="&cutCmd.label;" accesskey="&cut.accesskey;" command="cmd_cut"/>
+ <menuitem id="menu_copy_cm" label="©Cmd.label;" accesskey="©.accesskey;" command="cmd_copy"/>
+ <menuitem id="menu_paste_cm" label="&pasteCmd.label;" accesskey="&paste.accesskey;" command="cmd_paste"/>
+ <menuitem id="menu_pasteNoFormatting_cm" command="cmd_pasteNoFormatting"/>
+ <menuitem id="menu_delete_cm" label="&deleteCmd.label;" accesskey="&delete.accesskey;" command="cmd_delete"/>
+ <menuseparator id="edit-separator"/>
+ <menuitem id="menu_selectAll_cm" label="&selectAllCmd.label;" accesskey="&selectall.accesskey;" command="cmd_selectAll"/>
+ <menuseparator id="selectAll-separator"/>
+
+ <!-- label and accesskey set at runtime from strings -->
+ <menuitem id="removeStylesMenuitem_cm"
+ observes="cmd_removeStyles"/>
+ <menuitem id="createLink_cm" label="&createLinkCmd.label;" accesskey="&createlink.accesskey;" command="cmd_link"/>
+ <!-- label and accesskey set at runtime from strings -->
+ <menuitem id="removeLinksMenuitem_cm" observes="cmd_removeLinks"/>
+ <menuitem id="removeNamedAnchorsMenuitem_cm" label="&formatRemoveNamedAnchors.label;"
+ accesskey="&formatRemoveNamedAnchors.accesskey;"
+ observes="cmd_removeNamedAnchors"/>
+ <menuseparator id="styles-separator"/>
+
+ <!-- label and accesskey are set in InitObjectProperties -->
+ <menuitem id="objectProperties_cm" observes="cmd_objectProperties"/>
+ <menuitem id="editLink_cm" label="&editLinkCmd.label;" accesskey="&editlink.accesskey;" command="cmd_editLink"/>
+ <menuseparator id="property-separator"/>
+
+ <!-- Can't get submenus to load from a shared overlay -->
+ <menu id="tableInsertMenu_cm" label="&tableInsertMenu2.label;" accesskey="&tableinsertmenu.accesskey;">
+ <menupopup>
+ <menuitem label="&insertTableCmd.label;" accesskey="&tabletable.accesskey;" observes="cmd_InsertTable"/>
+ <menuseparator />
+ <menuitem label="&tableRowAbove.label;" accesskey="&tablerow.accesskey;" observes="cmd_InsertRowAbove"/>
+ <menuitem label="&tableRowBelow.label;" accesskey="&tablerowbelow.accesskey;" observes="cmd_InsertRowBelow"/>
+ <menuseparator />
+ <menuitem label="&tableColumnBefore.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_InsertColumnBefore"/>
+ <menuitem label="&tableColumnAfter.label;" accesskey="&tablecolumnafter.accesskey;" observes="cmd_InsertColumnAfter"/>
+ <menuseparator />
+ <menuitem label="&tableCellBefore.label;" accesskey="&tablecell.accesskey;" observes="cmd_InsertCellBefore"/>
+ <menuitem label="&tableCellAfter.label;" accesskey="&tablecellafter.accesskey;" observes="cmd_InsertCellAfter"/>
+ </menupopup>
+ </menu>
+ <menu id="tableSelectMenu_cm" label="&tableSelectMenu2.label;" accesskey="&tableselectmenu.accesskey;">
+ <menupopup>
+ <menuitem id="menu_SelectTable_cm" label="&tableTable.label;" accesskey="&tabletable.accesskey;" observes="cmd_SelectTable" />
+ <menuitem id="menu_SelectRow_cm" label="&tableRow.label;" accesskey="&tablerow.accesskey;" observes="cmd_SelectRow" />
+ <menuitem id="menu_SelectColumn_cm" label="&tableColumn.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_SelectColumn" />
+ <menuitem id="menu_SelectCell_cm" label="&tableCell.label;" accesskey="&tablecell.accesskey;" observes="cmd_SelectCell" />
+ <menuitem id="menu_SelectAllCells_cm" label="&tableAllCells.label;" accesskey="&tableallcells.accesskey;" observes="cmd_SelectAllCells" />
+ </menupopup>
+ </menu>
+ <menu id="tableDeleteMenu_cm" label="&tableDeleteMenu2.label;" accesskey="&tabledeletemenu.accesskey;">
+ <menupopup>
+ <menuitem id="menu_DeleteTable_cm" label="&tableTable.label;" accesskey="&tabletable.accesskey;" observes="cmd_DeleteTable"/>
+ <menuitem id="menu_DeleteRow_cm" label="&tableRows.label;" accesskey="&tablerow.accesskey;" observes="cmd_DeleteRow"/>
+ <menuitem id="menu_DeleteColumn_cm" label="&tableColumns.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_DeleteColumn"/>
+ <menuitem id="menu_DeleteCell_cm" label="&tableCells.label;" accesskey="&tablecell.accesskey;" observes="cmd_DeleteCell"/>
+ <menuitem id="menu_DeleteCellContents_cm" label="&tableCellContents.label;" accesskey="&tablecellcontents.accesskey;" observes="cmd_DeleteCellContents"/>
+ </menupopup>
+ </menu>
+ <!-- menu label is set in InitTableMenu -->
+ <menuitem id="joinTableCells_cm" label="&tableJoinCells.label;" accesskey="&tablejoincells.accesskey;" observes="cmd_JoinTableCells"/>
+ <menuitem id="splitTableCell_cm" label="&tableSplitCell.label;" accesskey="&tablesplitcell.accesskey;" observes="cmd_SplitTableCell"/>
+ <menuitem id="tableOrCellColor_cm" label="&tableOrCellColor.label;" accesskey="&tableOrCellColor.accesskey;" observes="cmd_TableOrCellColor"/>
+ </popup>
+
+ <popup id="editorSourceContext">
+ <menuitem label="&undoCmd.label;" accesskey="&undo.accesskey;" command="cmd_undo"/>
+ <menuitem label="&redoCmd.label;" accesskey="&redo.accesskey;" command="cmd_redo"/>
+ <menuseparator/>
+ <menuitem label="&cutCmd.label;" accesskey="&cut.accesskey;" command="cmd_cut"/>
+ <menuitem label="©Cmd.label;" accesskey="©.accesskey;" command="cmd_copy"/>
+ <menuitem label="&pasteCmd.label;" accesskey="&paste.accesskey;" command="cmd_paste"/>
+ <menuitem label="&deleteCmd.label;" accesskey="&delete.accesskey;" command="cmd_delete"/>
+ <menuseparator/>
+ <menuitem label="&selectAllCmd.label;" accesskey="&selectall.accesskey;" command="cmd_selectAll"/>
+ </popup>
+
+ <popup id="structToolbarContext">
+ <menuitem id="structSelect" label="&structSelect.label;"
+ accesskey="&structSelect.accesskey;"
+ oncommand="StructSelectTag()"/>
+ <menuseparator/>
+ <menuitem id="structRemoveTag" label="&structRemoveTag.label;"
+ accesskey="&structRemoveTag.accesskey;"
+ oncommand="StructRemoveTag()"/>
+ <menuitem id="structChangeTag" label="&structChangeTag.label;"
+ accesskey="&structChangeTag.accesskey;"
+ oncommand="StructChangeTag()"/>
+ <menuseparator/>
+ <menuitem id="advancedPropsTag" label="&advancedPropertiesCmd.label;"
+ accesskey="&advancedproperties.accesskey;"
+ oncommand="OpenAdvancedProperties()"/>
+ </popup>
+
+</popupset>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/EditorParagraphMarks.css
@@ -0,0 +1,49 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* This adds the standard paragraph symbol
+ * after paragraphs (block container tags)
+*/
+
+p:after,br:after,
+h1:after,h2:after,h3:after,h4:after,h5:after,h6:after,
+address:after,blockquote:after,listing:after,
+plaintext:after, xmp:after, pre:after,
+li:after,dt:after,dd:after
+{
+ content: "\B6 ";
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/StructBarContextMenu.js
@@ -0,0 +1,212 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Daniel Glazman (glazman@netscape.com), original author
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gContextMenuNode;
+var gContextMenuFiringDocumentElement;
+
+function InitStructBarContextMenu(button, docElement)
+{
+ gContextMenuFiringDocumentElement = docElement;
+ gContextMenuNode = button;
+
+ var tag = docElement.nodeName.toLowerCase();
+
+ var structRemoveTag = document.getElementById("structRemoveTag");
+ var enableRemove;
+
+ switch (tag) {
+ case "body":
+ case "tbody":
+ case "thead":
+ case "tfoot":
+ case "col":
+ case "colgroup":
+ case "tr":
+ case "th":
+ case "td":
+ case "caption":
+ enableRemove = false;
+ break;
+ default:
+ enableRemove = true;
+ break;
+ }
+ SetElementEnabled(structRemoveTag, enableRemove);
+
+ var structChangeTag = document.getElementById("structChangeTag");
+ SetElementEnabled(structChangeTag, (tag != "body"));
+}
+
+function TableCellFilter(node)
+{
+ switch (node.nodeName.toLowerCase())
+ {
+ case "td":
+ case "th":
+ case "caption":
+ return NodeFilter.FILTER_ACCEPT;
+ break;
+ default:
+ return NodeFilter.FILTER_SKIP;
+ break;
+ }
+ return NodeFilter.FILTER_SKIP;
+}
+
+function StructRemoveTag()
+{
+ var editor = GetCurrentEditor();
+ if (!editor) return;
+
+ var element = gContextMenuFiringDocumentElement;
+ var offset = 0;
+ var childNodes = element.parentNode.childNodes;
+
+ while (childNodes[offset] != element) {
+ ++offset;
+ }
+
+ editor.beginTransaction();
+
+ try {
+
+ var tag = element.nodeName.toLowerCase();
+ if (tag != "table") {
+ MoveChildNodesAfterElement(editor, element, element, offset);
+ }
+ else {
+
+ var nodeIterator = document.createTreeWalker(element,
+ NodeFilter.SHOW_ELEMENT,
+ TableCellFilter,
+ true);
+ var node = nodeIterator.lastChild();
+ while (node) {
+ MoveChildNodesAfterElement(editor, node, element, offset);
+ node = nodeIterator.previousSibling();
+ }
+
+ }
+ editor.deleteNode(element);
+ }
+ catch (e) {};
+
+ editor.endTransaction();
+}
+
+function MoveChildNodesAfterElement(editor, element, targetElement, targetOffset)
+{
+ var childNodes = element.childNodes;
+ var childNodesLength = childNodes.length;
+ var i;
+ for (i = childNodesLength - 1; i >= 0; i--) {
+ var clone = childNodes.item(i).cloneNode(true);
+ editor.insertNode(clone, targetElement.parentNode, targetOffset + 1);
+ }
+}
+
+function StructChangeTag()
+{
+ var textbox = document.createElementNS(XUL_NS, "textbox");
+ textbox.setAttribute("value", gContextMenuNode.getAttribute("value"));
+ textbox.setAttribute("width", gContextMenuNode.boxObject.width);
+ textbox.className = "struct-textbox";
+
+ gContextMenuNode.parentNode.replaceChild(textbox, gContextMenuNode);
+
+ textbox.addEventListener("keypress", OnKeyPress, false);
+ textbox.addEventListener("blur", ResetStructToolbar, true);
+
+ textbox.select();
+}
+
+function StructSelectTag()
+{
+ SelectFocusNodeAncestor(gContextMenuFiringDocumentElement);
+}
+
+function OpenAdvancedProperties()
+{
+ doAdvancedProperties(gContextMenuFiringDocumentElement);
+}
+
+function OnKeyPress(event)
+{
+ var editor = GetCurrentEditor();
+
+ var keyCode = event.keyCode;
+ if (keyCode == 13) {
+ var newTag = event.target.value;
+
+ var element = gContextMenuFiringDocumentElement;
+
+ var offset = 0;
+ var childNodes = element.parentNode.childNodes;
+ while (childNodes.item(offset) != element) {
+ offset++;
+ }
+
+ editor.beginTransaction();
+
+ try {
+ var newElt = editor.document.createElement(newTag);
+ if (newElt) {
+ childNodes = element.childNodes;
+ var childNodesLength = childNodes.length;
+ var i;
+ for (i = 0; i < childNodesLength; i++) {
+ var clone = childNodes.item(i).cloneNode(true);
+ newElt.appendChild(clone);
+ }
+ editor.insertNode(newElt, element.parentNode, offset+1);
+ editor.deleteNode(element);
+ editor.selectElement(newElt);
+
+ window.content.focus();
+ }
+ }
+ catch (e) {}
+
+ editor.endTransaction();
+
+ }
+ else if (keyCode == 27) {
+ // if the user hits Escape, we discard the changes
+ window.content.focus();
+ }
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/composerOverlay.xul
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manske (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<overlay id="composerOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- Items in the Edit menu used only by Composer app -->
+ <menupopup id="edEditMenuPopup">
+ <menuitem id="menu_publishSettings" insertafter="menu_prefsSep" observes="cmd_publishSettings"/>
+ </menupopup>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editor.js
@@ -0,0 +1,3468 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sammy Ford (sford@swbell.net)
+ * Dan Haddix (dan6992@hotmail.com)
+ * John Ratke (jratke@owc.net)
+ * Ryan Cassin (rcassin@supernova.org)
+ * Daniel Glazman (glazman@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Main Composer window UI control */
+
+var gComposerWindowControllerID = 0;
+var prefAuthorString = "";
+
+const kDisplayModeNormal = 0;
+const kDisplayModeAllTags = 1;
+const kDisplayModeSource = 2;
+const kDisplayModePreview = 3;
+const kDisplayModeMenuIDs = ["viewNormalMode", "viewAllTagsMode", "viewSourceMode", "viewPreviewMode"];
+const kDisplayModeTabIDS = ["NormalModeButton", "TagModeButton", "SourceModeButton", "PreviewModeButton"];
+const kNormalStyleSheet = "chrome://editor/content/EditorContent.css";
+const kAllTagsStyleSheet = "chrome://editor/content/EditorAllTags.css";
+const kParagraphMarksStyleSheet = "chrome://editor/content/EditorParagraphMarks.css";
+const kContentEditableStyleSheet = "resource://gre/res/contenteditable.css";
+
+const kTextMimeType = "text/plain";
+const kHTMLMimeType = "text/html";
+
+const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
+
+var gPreviousNonSourceDisplayMode = 1;
+var gEditorDisplayMode = -1;
+var gDocWasModified = false; // Check if clean document, if clean then unload when user "Opens"
+var gContentWindow = 0;
+var gSourceContentWindow = 0;
+var gSourceTextEditor = null;
+var gContentWindowDeck;
+var gFormatToolbar;
+var gFormatToolbarHidden = false;
+var gViewFormatToolbar;
+var gColorObj = { LastTextColor:"", LastBackgroundColor:"", LastHighlightColor:"",
+ Type:"", SelectedType:"", NoDefault:false, Cancel:false,
+ HighlightColor:"", BackgroundColor:"", PageColor:"",
+ TextColor:"", TableColor:"", CellColor:""
+ };
+var gDefaultTextColor = "";
+var gDefaultBackgroundColor = "";
+var gCSSPrefListener;
+var gEditorToolbarPrefListener;
+var gReturnInParagraphPrefListener;
+var gPrefs;
+var gLocalFonts = null;
+
+var gLastFocusNode = null;
+var gLastFocusNodeWasSelected = false;
+
+// These must be kept in synch with the XUL <options> lists
+var gFontSizeNames = ["xx-small","x-small","small","medium","large","x-large","xx-large"];
+
+const nsIFilePicker = Components.interfaces.nsIFilePicker;
+
+const kEditorToolbarPrefs = "editor.toolbars.showbutton.";
+const kUseCssPref = "editor.use_css";
+const kCRInParagraphsPref = "editor.CR_creates_new_p";
+
+function ShowHideToolbarSeparators(toolbar) {
+ var childNodes = toolbar.childNodes;
+ var separator = null;
+ var hideSeparator = true;
+ for (var i = 0; childNodes[i].localName != "spacer"; i++) {
+ if (childNodes[i].localName == "toolbarseparator") {
+ if (separator)
+ separator.hidden = true;
+ separator = childNodes[i];
+ } else if (!childNodes[i].hidden) {
+ if (separator)
+ separator.hidden = hideSeparator;
+ separator = null;
+ hideSeparator = false;
+ }
+ }
+}
+
+function ShowHideToolbarButtons()
+{
+ var array = gPrefs.getChildList(kEditorToolbarPrefs, {});
+ for (var i in array) {
+ var prefName = array[i];
+ var id = prefName.substr(kEditorToolbarPrefs.length) + "Button";
+ var button = document.getElementById(id);
+ if (button)
+ button.hidden = !gPrefs.getBoolPref(prefName);
+ }
+ ShowHideToolbarSeparators(document.getElementById("EditToolbar"));
+ ShowHideToolbarSeparators(document.getElementById("FormatToolbar"));
+}
+
+function nsPrefListener(prefName)
+{
+ this.startup(prefName);
+}
+
+// implements nsIObserver
+nsPrefListener.prototype =
+{
+ domain: "",
+ startup: function(prefName)
+ {
+ this.domain = prefName;
+ try {
+ var pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranch2);
+ pbi.addObserver(this.domain, this, false);
+ } catch(ex) {
+ dump("Failed to observe prefs: " + ex + "\n");
+ }
+ },
+ shutdown: function()
+ {
+ try {
+ var pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranch2);
+ pbi.removeObserver(this.domain, this);
+ } catch(ex) {
+ dump("Failed to remove pref observers: " + ex + "\n");
+ }
+ },
+ observe: function(subject, topic, prefName)
+ {
+ if (!IsHTMLEditor())
+ return;
+ // verify that we're changing a button pref
+ if (topic != "nsPref:changed") return;
+
+ var editor = GetCurrentEditor();
+ if (prefName == kUseCssPref)
+ {
+ var cmd = document.getElementById("cmd_highlight");
+ if (cmd) {
+ var useCSS = gPrefs.getBoolPref(prefName);
+
+ if (useCSS && editor) {
+ var mixedObj = {};
+ var state = editor.getHighlightColorState(mixedObj);
+ cmd.setAttribute("state", state);
+ cmd.collapsed = false;
+ }
+ else {
+ cmd.setAttribute("state", "transparent");
+ cmd.collapsed = true;
+ }
+
+ if (editor)
+ editor.isCSSEnabled = useCSS;
+ }
+ }
+ else if (prefName.substr(0, kEditorToolbarPrefs.length) == kEditorToolbarPrefs)
+ {
+ var id = prefName.substr(kEditorToolbarPrefs.length) + "Button";
+ var button = document.getElementById(id);
+ if (button) {
+ button.hidden = !gPrefs.getBoolPref(prefName);
+ ShowHideToolbarSeparators(button.parentNode);
+ }
+ }
+ else if (editor && (prefName == kCRInParagraphsPref))
+ editor.returnInParagraphCreatesNewParagraph = gPrefs.getBoolPref(prefName);
+ }
+}
+
+function AfterHighlightColorChange()
+{
+ if (!IsHTMLEditor())
+ return;
+
+ var button = document.getElementById("cmd_highlight");
+ if (button) {
+ var mixedObj = {};
+ try {
+ var state = GetCurrentEditor().getHighlightColorState(mixedObj);
+ button.setAttribute("state", state);
+ onHighlightColorChange();
+ } catch (e) {}
+ }
+}
+
+function EditorOnLoad()
+{
+ // See if argument was passed.
+ if ( window.arguments && window.arguments[0] ) {
+ // Opened via window.openDialog with URL as argument.
+ // Put argument where EditorStartup expects it.
+ document.getElementById( "args" ).setAttribute( "value", window.arguments[0] );
+ }
+
+ // get default character set if provided
+ if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
+ if (window.arguments[1].indexOf("charset=") != -1) {
+ var arrayArgComponents = window.arguments[1].split("=");
+ if (arrayArgComponents) {
+ // Put argument where EditorStartup expects it.
+ document.getElementById( "args" ).setAttribute("charset", arrayArgComponents[1]);
+ }
+ }
+ }
+
+ window.tryToClose = EditorCanClose;
+
+ // Continue with normal startup.
+ EditorStartup();
+
+ // Initialize our source text <editor>
+ try {
+ gSourceContentWindow = document.getElementById("content-source");
+ gSourceContentWindow.makeEditable("text", false);
+ gSourceTextEditor = gSourceContentWindow.getEditor(gSourceContentWindow.contentWindow);
+ gSourceTextEditor.QueryInterface(Components.interfaces.nsIPlaintextEditor);
+ gSourceTextEditor.enableUndo(false);
+ gSourceTextEditor.rootElement.style.fontFamily = "-moz-fixed";
+ gSourceTextEditor.rootElement.style.whiteSpace = "pre";
+ gSourceTextEditor.rootElement.style.margin = 0;
+ var controller = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"]
+ .createInstance(Components.interfaces.nsIControllerContext);
+ controller.init(null);
+ controller.setCommandContext(gSourceContentWindow);
+ gSourceContentWindow.contentWindow.controllers.insertControllerAt(0, controller);
+ var commandTable = controller.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIControllerCommandTable);
+ commandTable.registerCommand("cmd_find", nsFindCommand);
+ commandTable.registerCommand("cmd_findNext", nsFindAgainCommand);
+ commandTable.registerCommand("cmd_findPrev", nsFindAgainCommand);
+ } catch (e) { dump("makeEditable failed: "+e+"\n"); }
+}
+
+const gSourceTextListener =
+{
+ NotifyDocumentCreated: function NotifyDocumentCreated() {},
+ NotifyDocumentWillBeDestroyed: function NotifyDocumentWillBeDestroyed() {},
+ NotifyDocumentStateChanged: function NotifyDocumentStateChanged(isChanged)
+ {
+ window.updateCommands("save");
+ }
+};
+
+const gSourceTextObserver =
+{
+ observe: function observe(aSubject, aTopic, aData)
+ {
+ // we currently only use this to update undo
+ window.updateCommands("undo");
+ }
+};
+
+function TextEditorOnLoad()
+{
+ // See if argument was passed.
+ if ( window.arguments && window.arguments[0] ) {
+ // Opened via window.openDialog with URL as argument.
+ // Put argument where EditorStartup expects it.
+ document.getElementById( "args" ).setAttribute( "value", window.arguments[0] );
+ }
+ // Continue with normal startup.
+ EditorStartup();
+}
+
+// This should be called by all editor users when they close their window
+// or other similar "done with editor" actions, like recycling a Mail Composer window.
+function EditorCleanup()
+{
+ SwitchInsertCharToAnotherEditorOrClose();
+}
+
+var DocumentReloadListener =
+{
+ NotifyDocumentCreated: function() {},
+ NotifyDocumentWillBeDestroyed: function() {},
+
+ NotifyDocumentStateChanged:function( isNowDirty )
+ {
+ var editor = GetCurrentEditor();
+ try {
+ // unregister the listener to prevent multiple callbacks
+ editor.removeDocumentStateListener( DocumentReloadListener );
+
+ var charset = editor.documentCharacterSet;
+
+ // update the META charset with the current presentation charset
+ editor.documentCharacterSet = charset;
+
+ } catch (e) {}
+ }
+};
+
+function addEditorClickEventListener()
+{
+ try {
+ var bodyelement = GetBodyElement();
+ if (bodyelement)
+ bodyelement.addEventListener("click", EditorClick, false);
+ } catch (e) {}
+}
+
+// implements nsIObserver
+var gEditorDocumentObserver =
+{
+ observe: function(aSubject, aTopic, aData)
+ {
+ // Should we allow this even if NOT the focused editor?
+ var commandManager = GetCurrentCommandManager();
+ if (commandManager != aSubject)
+ return;
+
+ var editor = GetCurrentEditor();
+ switch(aTopic)
+ {
+ case "obs_documentCreated":
+ // Just for convenience
+ gContentWindow = window.content;
+
+ // Get state to see if document creation succeeded
+ var params = newCommandParams();
+ if (!params)
+ return;
+
+ try {
+ commandManager.getCommandState(aTopic, gContentWindow, params);
+ var errorStringId = 0;
+ var editorStatus = params.getLongValue("state_data");
+ if (!editor && editorStatus == nsIEditingSession.eEditorOK)
+ {
+ dump("\n ****** NO EDITOR BUT NO EDITOR ERROR REPORTED ******* \n\n");
+ editorStatus = nsIEditingSession.eEditorErrorUnknown;
+ }
+
+ switch (editorStatus)
+ {
+ case nsIEditingSession.eEditorErrorCantEditFramesets:
+ errorStringId = "CantEditFramesetMsg";
+ break;
+ case nsIEditingSession.eEditorErrorCantEditMimeType:
+ errorStringId = "CantEditMimeTypeMsg";
+ break;
+ case nsIEditingSession.eEditorErrorUnknown:
+ errorStringId = "CantEditDocumentMsg";
+ break;
+ // Note that for "eEditorErrorFileNotFound,
+ // network code popped up an alert dialog, so we don't need to
+ }
+ if (errorStringId)
+ AlertWithTitle("", GetString(errorStringId));
+ } catch(e) { dump("EXCEPTION GETTING obs_documentCreated state "+e+"\n"); }
+
+ // We have a bad editor -- nsIEditingSession will rebuild an editor
+ // with a blank page, so simply abort here
+ if (editorStatus)
+ return;
+
+ if (!("InsertCharWindow" in window))
+ window.InsertCharWindow = null;
+
+ try {
+ editor.QueryInterface(nsIEditorStyleSheets);
+
+ // and extra styles for showing anchors, table borders, smileys, etc
+ editor.addOverrideStyleSheet(kNormalStyleSheet);
+
+ // remove contenteditable stylesheets if they were applied by the
+ // editingSession
+ editor.removeOverrideStyleSheet(kContentEditableStyleSheet);
+ } catch (e) {}
+
+ // Things for just the Web Composer application
+ if (IsWebComposer())
+ {
+ InlineSpellCheckerUI.init(editor);
+ document.getElementById('menu_inlinespellcheck').setAttribute('disabled', !InlineSpellCheckerUI.canSpellCheck);
+
+ editor.returnInParagraphCreatesNewParagraph = gPrefs.getBoolPref(kCRInParagraphsPref);
+
+ // Set focus to content window if not a mail composer
+ // Race conditions prevent us from setting focus here
+ // when loading a url into blank window
+ setTimeout(SetFocusOnStartup, 0);
+
+ // Call EditorSetDefaultPrefsAndDoctype first so it gets the default author before initing toolbars
+ EditorSetDefaultPrefsAndDoctype();
+
+ // We may load a text document into an html editor,
+ // so be sure editortype is set correctly
+ // XXX We really should use the "real" plaintext editor for this!
+ if (editor.contentsMIMEType == "text/plain")
+ {
+ try {
+ GetCurrentEditorElement().editortype = "text";
+ } catch (e) { dump (e)+"\n"; }
+
+ // Hide or disable UI not used for plaintext editing
+ HideItem("FormatToolbar");
+ HideItem("EditModeToolbar");
+ HideItem("formatMenu");
+ HideItem("tableMenu");
+ HideItem("menu_validate");
+ HideItem("sep_validate");
+ HideItem("previewButton");
+ HideItem("imageButton");
+ HideItem("linkButton");
+ HideItem("namedAnchorButton");
+ HideItem("hlineButton");
+ HideItem("tableButton");
+
+ HideItem("fileExportToText");
+ HideItem("previewInBrowser");
+
+/* XXX When paste actually converts formatted rich text to pretty formatted plain text
+ and pasteNoFormatting is fixed to paste the text without formatting (what paste
+ currently does), then this item shouldn't be hidden: */
+ HideItem("menu_pasteNoFormatting");
+
+ HideItem("cmd_viewFormatToolbar");
+ HideItem("cmd_viewEditModeToolbar");
+
+ HideItem("viewSep1");
+ HideItem("viewNormalMode");
+ HideItem("viewAllTagsMode");
+ HideItem("viewSourceMode");
+ HideItem("viewPreviewMode");
+
+ HideItem("structSpacer");
+
+ // Hide everything in "Insert" except for "Symbols"
+ var menuPopup = document.getElementById("insertMenuPopup");
+ if (menuPopup)
+ {
+ var children = menuPopup.childNodes;
+ for (var i=0; i < children.length; i++)
+ {
+ var item = children.item(i);
+ if (item.id != "insertChars")
+ item.hidden = true;
+ }
+ }
+ }
+
+ // Set window title
+ UpdateWindowTitle();
+
+ // We must wait until document is created to get proper Url
+ // (Windows may load with local file paths)
+ SetSaveAndPublishUI(GetDocumentUrl());
+
+ // Start in "Normal" edit mode
+ SetDisplayMode(kDisplayModeNormal);
+ }
+
+ // Add mouse click watcher if right type of editor
+ if (IsHTMLEditor())
+ {
+ addEditorClickEventListener();
+
+ // Force color widgets to update
+ onFontColorChange();
+ onBackgroundColorChange();
+ }
+ break;
+
+ case "cmd_setDocumentModified":
+ window.updateCommands("save");
+ break;
+
+ case "obs_documentWillBeDestroyed":
+ dump("obs_documentWillBeDestroyed notification\n");
+ break;
+
+ case "obs_documentLocationChanged":
+ // Ignore this when editor doesn't exist,
+ // which happens once when page load starts
+ if (editor)
+ try {
+ editor.updateBaseURL();
+ } catch(e) { dump (e); }
+ break;
+
+ case "cmd_bold":
+ // Update all style items
+ // cmd_bold is a proxy; see EditorSharedStartup (above) for details
+ window.updateCommands("style");
+ window.updateCommands("undo");
+ break;
+ }
+ }
+}
+
+function SetFocusOnStartup()
+{
+ gContentWindow.focus();
+}
+
+function EditorStartup()
+{
+ var ds = GetCurrentEditorElement().docShell;
+ ds.useErrorPages = false;
+ var root = ds.QueryInterface(Components.interfaces.nsIDocShellTreeItem).
+ rootTreeItem.QueryInterface(Components.interfaces.nsIDocShell);
+
+ root.QueryInterface(Components.interfaces.nsIDocShell).appType =
+ Components.interfaces.nsIDocShell.APP_TYPE_EDITOR;
+
+ var is_HTMLEditor = IsHTMLEditor();
+ if (is_HTMLEditor)
+ {
+ // XUL elements we use when switching from normal editor to edit source
+ gContentWindowDeck = document.getElementById("ContentWindowDeck");
+ gFormatToolbar = document.getElementById("FormatToolbar");
+ gViewFormatToolbar = document.getElementById("viewFormatToolbar");
+ }
+
+ // set up our global prefs object
+ GetPrefsService();
+
+ // Startup also used by other editor users, such as Message Composer
+ EditorSharedStartup();
+
+ // Commands specific to the Composer Application window,
+ // (i.e., not embedded editors)
+ // such as file-related commands, HTML Source editing, Edit Modes...
+ SetupComposerWindowCommands();
+
+ ShowHideToolbarButtons();
+ gEditorToolbarPrefListener = new nsPrefListener(kEditorToolbarPrefs);
+
+ gCSSPrefListener = new nsPrefListener(kUseCssPref);
+ gReturnInParagraphPrefListener = new nsPrefListener(kCRInParagraphsPref);
+
+ // hide Highlight button if we are in an HTML editor with CSS mode off
+ // and tell the editor if a CR in a paragraph creates a new paragraph
+ var cmd = document.getElementById("cmd_highlight");
+ if (cmd) {
+ var useCSS = gPrefs.getBoolPref(kUseCssPref);
+ if (!useCSS && is_HTMLEditor) {
+ cmd.collapsed = true;
+ }
+ }
+
+ // Get url for editor content and load it.
+ // the editor gets instantiated by the edittingSession when the URL has finished loading.
+ var url = document.getElementById("args").getAttribute("value");
+ try {
+ var charset = document.getElementById("args").getAttribute("charset");
+ var contentViewer = GetCurrentEditorElement().docShell.contentViewer;
+ contentViewer.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+ contentViewer.defaultCharacterSet = charset;
+ contentViewer.forceCharacterSet = charset;
+ } catch (e) {}
+ EditorLoadUrl(url);
+}
+
+function EditorLoadUrl(url)
+{
+ try {
+ if (url)
+ GetCurrentEditorElement().webNavigation.loadURI(url, // uri string
+ nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE, // load flags
+ null, // referrer
+ null, // post-data stream
+ null);
+ } catch (e) { dump(" EditorLoadUrl failed: "+e+"\n"); }
+}
+
+// This should be called by all Composer types
+function EditorSharedStartup()
+{
+ // Just for convenience
+ gContentWindow = window.content;
+
+ // Set up the mime type and register the commands.
+ if (IsHTMLEditor())
+ SetupHTMLEditorCommands();
+ else
+ SetupTextEditorCommands();
+
+ // add observer to be called when document is really done loading
+ // and is modified
+ // Note: We're really screwed if we fail to install this observer!
+ try {
+ var commandManager = GetCurrentCommandManager();
+ commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentCreated");
+ commandManager.addCommandObserver(gEditorDocumentObserver, "cmd_setDocumentModified");
+ commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentWillBeDestroyed");
+ commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentLocationChanged");
+
+ // Until nsIControllerCommandGroup-based code is implemented,
+ // we will observe just the bold command to trigger update of
+ // all toolbar style items
+ commandManager.addCommandObserver(gEditorDocumentObserver, "cmd_bold");
+ } catch (e) { dump(e); }
+
+ var isMac = (GetOS() == gMac);
+
+ // Set platform-specific hints for how to select cells
+ // Mac uses "Cmd", all others use "Ctrl"
+ var tableKey = GetString(isMac ? "XulKeyMac" : "TableSelectKey");
+ var dragStr = tableKey+GetString("Drag");
+ var clickStr = tableKey+GetString("Click");
+
+ var delStr = GetString(isMac ? "Clear" : "Del");
+
+ SafeSetAttribute("menu_SelectCell", "acceltext", clickStr);
+ SafeSetAttribute("menu_SelectRow", "acceltext", dragStr);
+ SafeSetAttribute("menu_SelectColumn", "acceltext", dragStr);
+ SafeSetAttribute("menu_SelectAllCells", "acceltext", dragStr);
+ // And add "Del" or "Clear"
+ SafeSetAttribute("menu_DeleteCellContents", "acceltext", delStr);
+
+ // Set text for indent, outdent keybinding
+
+ // hide UI that we don't have components for
+ RemoveInapplicableUIElements();
+
+ gPrefs = GetPrefs();
+
+ // Use browser colors as initial values for editor's default colors
+ var BrowserColors = GetDefaultBrowserColors();
+ if (BrowserColors)
+ {
+ gDefaultTextColor = BrowserColors.TextColor;
+ gDefaultBackgroundColor = BrowserColors.BackgroundColor;
+ }
+
+ // For new window, no default last-picked colors
+ gColorObj.LastTextColor = "";
+ gColorObj.LastBackgroundColor = "";
+ gColorObj.LastHighlightColor = "";
+}
+
+// This method is only called by Message composer when recycling a compose window
+function EditorResetFontAndColorAttributes()
+{
+ try {
+ var editor = GetCurrentEditor();
+ editor.rebuildDocumentFromSource("");
+ // Because the selection is now collapsed, the following line
+ // clears the typing state to discontinue all inline styles
+ editor.removeAllInlineProperties();
+ document.getElementById("cmd_fontFace").setAttribute("state", "");
+ gColorObj.LastTextColor = "";
+ gColorObj.LastBackgroundColor = "";
+ gColorObj.LastHighlightColor = "";
+ document.getElementById("cmd_fontColor").setAttribute("state", "");
+ document.getElementById("cmd_backgroundColor").setAttribute("state", "");
+ UpdateDefaultColors();
+ } catch (e) {}
+}
+
+function EditorShutdown()
+{
+ gEditorToolbarPrefListener.shutdown();
+ gCSSPrefListener.shutdown();
+ gReturnInParagraphPrefListener.shutdown();
+
+ try {
+ var commandManager = GetCurrentCommandManager();
+ commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentCreated");
+ commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentWillBeDestroyed");
+ commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentLocationChanged");
+ } catch (e) { dump (e); }
+}
+
+function SafeSetAttribute(nodeID, attributeName, attributeValue)
+{
+ var theNode = document.getElementById(nodeID);
+ if (theNode)
+ theNode.setAttribute(attributeName, attributeValue);
+}
+
+function DocumentHasBeenSaved()
+{
+ var fileurl = "";
+ try {
+ fileurl = GetDocumentUrl();
+ } catch (e) {
+ return false;
+ }
+
+ if (!fileurl || IsUrlAboutBlank(fileurl))
+ return false;
+
+ // We have a file URL already
+ return true;
+}
+
+function CheckAndSaveDocument(command, allowDontSave)
+{
+ var document;
+ try {
+ // if we don't have an editor or an document, bail
+ var editor = GetCurrentEditor();
+ document = editor.document;
+ if (!document)
+ return true;
+ } catch (e) { return true; }
+
+ if (!IsDocumentModified() && !IsHTMLSourceChanged())
+ return true;
+
+ // call window.focus, since we need to pop up a dialog
+ // and therefore need to be visible (to prevent user confusion)
+ top.document.commandDispatcher.focusedWindow.focus();
+
+ var scheme = GetScheme(GetDocumentUrl());
+ var doPublish = (scheme && scheme != "file");
+
+ var strID;
+ switch (command)
+ {
+ case "cmd_close":
+ strID = "BeforeClosing";
+ break;
+ case "cmd_preview":
+ strID = "BeforePreview";
+ break;
+ case "cmd_editSendPage":
+ strID = "SendPageReason";
+ break;
+ case "cmd_validate":
+ strID = "BeforeValidate";
+ break;
+ }
+
+ var reasonToSave = strID ? GetString(strID) : "";
+
+ var title = document.title;
+ if (!title)
+ title = GetString("untitled");
+
+ var dialogTitle = GetString(doPublish ? "PublishPage" : "SaveDocument");
+ var dialogMsg = GetString(doPublish ? "PublishPrompt" : "SaveFilePrompt");
+ dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave);
+
+ var promptService = GetPromptService();
+ if (!promptService)
+ return false;
+
+ var result = {value:0};
+ var promptFlags = promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1;
+ var button1Title = null;
+ var button3Title = null;
+
+ if (doPublish)
+ {
+ promptFlags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0;
+ button1Title = GetString("Publish");
+ button3Title = GetString("DontPublish");
+ }
+ else
+ {
+ promptFlags += promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0;
+ }
+
+ // If allowing "Don't..." button, add that
+ if (allowDontSave)
+ promptFlags += doPublish ?
+ (promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2)
+ : (promptService.BUTTON_TITLE_DONT_SAVE * promptService.BUTTON_POS_2);
+
+ result = promptService.confirmEx(window, dialogTitle, dialogMsg, promptFlags,
+ button1Title, null, button3Title, null, {value:0});
+
+ if (result == 0)
+ {
+ // Save, but first finish HTML source mode
+ if (IsHTMLSourceChanged()) {
+ try {
+ FinishHTMLSource();
+ } catch (e) { return false;}
+ }
+
+ if (doPublish)
+ {
+ // We save the command the user wanted to do in a global
+ // and return as if user canceled because publishing is asynchronous
+ // This command will be fired when publishing finishes
+ gCommandAfterPublishing = command;
+ goDoCommand("cmd_publish");
+ return false;
+ }
+
+ // Save to local disk
+ var contentsMIMEType;
+ if (IsHTMLEditor())
+ contentsMIMEType = kHTMLMimeType;
+ else
+ contentsMIMEType = kTextMimeType;
+ var success = SaveDocument(false, false, contentsMIMEType);
+ return success;
+ }
+
+ if (result == 2) // "Don't Save"
+ return true;
+
+ // Default or result == 1 (Cancel)
+ return false;
+}
+
+// --------------------------- File menu ---------------------------
+
+// Check for changes to document and allow saving before closing
+// This is hooked up to the OS's window close widget (e.g., "X" for Windows)
+function EditorCanClose()
+{
+ // Returns FALSE only if user cancels save action
+
+ // "true" means allow "Don't Save" button
+ var canClose = CheckAndSaveDocument("cmd_close", true);
+
+ // This is our only hook into closing via the "X" in the caption
+ // or "Quit" (or other paths?)
+ // so we must shift association to another
+ // editor or close any non-modal windows now
+ if (canClose && "InsertCharWindow" in window && window.InsertCharWindow)
+ SwitchInsertCharToAnotherEditorOrClose();
+
+ return canClose;
+}
+
+// --------------------------- View menu ---------------------------
+
+function EditorSetDocumentCharacterSet(aCharset)
+{
+ try {
+ var editor = GetCurrentEditor();
+ editor.documentCharacterSet = aCharset;
+ var docUrl = GetDocumentUrl();
+ if( !IsUrlAboutBlank(docUrl))
+ {
+ // reloading the document will reverse any changes to the META charset,
+ // we need to put them back in, which is achieved by a dedicated listener
+ editor.addDocumentStateListener( DocumentReloadListener );
+ EditorLoadUrl(docUrl);
+ }
+ } catch (e) {}
+}
+
+// ------------------------------------------------------------------
+function updateCharsetPopupMenu(menuPopup)
+{
+ if (IsDocumentModified() && !IsDocumentEmpty())
+ {
+ for (var i = 0; i < menuPopup.childNodes.length; i++)
+ {
+ var menuItem = menuPopup.childNodes[i];
+ menuItem.setAttribute('disabled', 'true');
+ }
+ }
+}
+
+// --------------------------- Text style ---------------------------
+
+function onParagraphFormatChange(paraMenuList, commandID)
+{
+ if (!paraMenuList)
+ return;
+
+ var commandNode = document.getElementById(commandID);
+ var state = commandNode.getAttribute("state");
+
+ // force match with "normal"
+ if (state == "body")
+ state = "";
+
+ if (state == "mixed")
+ {
+ //Selection is the "mixed" ( > 1 style) state
+ paraMenuList.selectedItem = null;
+ paraMenuList.setAttribute("label",GetString('Mixed'));
+ }
+ else
+ {
+ var menuPopup = document.getElementById("ParagraphPopup");
+ var menuItems = menuPopup.childNodes;
+ for (var i=0; i < menuItems.length; i++)
+ {
+ var menuItem = menuItems.item(i);
+ if ("value" in menuItem && menuItem.value == state)
+ {
+ paraMenuList.selectedItem = menuItem;
+ break;
+ }
+ }
+ }
+}
+
+function onFontFaceChange(fontFaceMenuList, commandID)
+{
+ var commandNode = document.getElementById(commandID);
+ var state = commandNode.getAttribute("state");
+
+ if (state == "mixed")
+ {
+ //Selection is the "mixed" ( > 1 style) state
+ fontFaceMenuList.selectedItem = null;
+ fontFaceMenuList.setAttribute("label",GetString('Mixed'));
+ }
+ else
+ {
+ var menuPopup = document.getElementById("FontFacePopup");
+ var menuItems = menuPopup.childNodes;
+ for (var i=0; i < menuItems.length; i++)
+ {
+ var menuItem = menuItems.item(i);
+ if (menuItem.getAttribute("label") && ("value" in menuItem && menuItem.value.toLowerCase() == state.toLowerCase()))
+ {
+ fontFaceMenuList.selectedItem = menuItem;
+ break;
+ }
+ }
+ }
+}
+
+function EditorSelectFontSize()
+{
+ var select = document.getElementById("FontSizeSelect");
+ if (select)
+ {
+ if (select.selectedIndex == -1)
+ return;
+
+ EditorSetFontSize(gFontSizeNames[select.selectedIndex]);
+ }
+}
+
+function onFontSizeChange(fontSizeMenulist, commandID)
+{
+ // If we don't match anything, set to "0 (normal)"
+ var newIndex = 2;
+ var size = fontSizeMenulist.getAttribute("size");
+ if ( size == "mixed")
+ {
+ // No single type selected
+ newIndex = -1;
+ }
+ else
+ {
+ for (var i = 0; i < gFontSizeNames.length; i++)
+ {
+ if( gFontSizeNames[i] == size )
+ {
+ newIndex = i;
+ break;
+ }
+ }
+ }
+ if (fontSizeMenulist.selectedIndex != newIndex)
+ fontSizeMenulist.selectedIndex = newIndex;
+}
+
+function EditorSetFontSize(size)
+{
+ if( size == "0" || size == "normal" ||
+ size == "medium" )
+ {
+ EditorRemoveTextProperty("font", "size");
+ // Also remove big and small,
+ // else it will seem like size isn't changing correctly
+ EditorRemoveTextProperty("small", "");
+ EditorRemoveTextProperty("big", "");
+ } else {
+ // Temp: convert from new CSS size strings to old HTML size strings
+ switch (size)
+ {
+ case "xx-small":
+ case "x-small":
+ size = "-2";
+ break;
+ case "small":
+ size = "-1";
+ break;
+ case "large":
+ size = "+1";
+ break;
+ case "x-large":
+ size = "+2";
+ break;
+ case "xx-large":
+ size = "+3";
+ break;
+ }
+ EditorSetTextProperty("font", "size", size);
+ }
+ gContentWindow.focus();
+}
+
+function initFontFaceMenu(menuPopup)
+{
+ initLocalFontFaceMenu(menuPopup);
+
+ if (menuPopup)
+ {
+ var children = menuPopup.childNodes;
+ if (!children) return;
+
+ var firstHas = { value: false };
+ var anyHas = { value: false };
+ var allHas = { value: false };
+
+ // we need to set or clear the checkmark for each menu item since the selection
+ // may be in a new location from where it was when the menu was previously opened
+
+ // Fixed width (second menu item) is special case: old TT ("teletype") attribute
+ EditorGetTextProperty("tt", "", "", firstHas, anyHas, allHas);
+ children[1].setAttribute("checked", allHas.value);
+
+ if (!anyHas.value)
+ EditorGetTextProperty("font", "face", "", firstHas, anyHas, allHas);
+
+ children[0].setAttribute("checked", !anyHas.value);
+
+ // Skip over default, TT, and separator
+ for (var i = 3; i < children.length; i++)
+ {
+ var menuItem = children[i];
+ var faceType = menuItem.getAttribute("value");
+
+ if (faceType)
+ {
+ EditorGetTextProperty("font", "face", faceType, firstHas, anyHas, allHas);
+
+ // Check the menuitem only if all of selection has the face
+ if (allHas.value)
+ {
+ menuItem.setAttribute("checked", "true");
+ break;
+ }
+
+ // in case none match, make sure we've cleared the checkmark
+ menuItem.removeAttribute("checked");
+ }
+ }
+ }
+}
+
+const kFixedFontFaceMenuItems = 7; // number of fixed font face menuitems
+
+function initLocalFontFaceMenu(menuPopup)
+{
+ if (!gLocalFonts)
+ {
+ // Build list of all local fonts once per editor
+ try
+ {
+ var enumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
+ .getService(Components.interfaces.nsIFontEnumerator);
+ var localFontCount = { value: 0 }
+ gLocalFonts = enumerator.EnumerateAllFonts(localFontCount);
+ }
+ catch(e) { }
+ }
+
+ var useRadioMenuitems = (menuPopup.parentNode.localName == "menu"); // don't do this for menulists
+ if (menuPopup.childNodes.length == kFixedFontFaceMenuItems)
+ {
+ if (gLocalFonts.length == 0) {
+ menuPopup.childNodes[kFixedFontFaceMenuItems - 1].hidden = true;
+ }
+ for (var i = 0; i < gLocalFonts.length; ++i)
+ {
+ if (gLocalFonts[i] != "")
+ {
+ var itemNode = document.createElementNS(XUL_NS, "menuitem");
+ itemNode.setAttribute("label", gLocalFonts[i]);
+ itemNode.setAttribute("value", gLocalFonts[i]);
+ if (useRadioMenuitems) {
+ itemNode.setAttribute("type", "radio");
+ itemNode.setAttribute("name", "2");
+ itemNode.setAttribute("observes", "cmd_renderedHTMLEnabler");
+ }
+ menuPopup.appendChild(itemNode);
+ }
+ }
+ }
+}
+
+
+function initFontSizeMenu(menuPopup)
+{
+ if (menuPopup)
+ {
+ var children = menuPopup.childNodes;
+ if (!children) return;
+
+ var firstHas = { value: false };
+ var anyHas = { value: false };
+ var allHas = { value: false };
+
+ var sizeWasFound = false;
+
+ // we need to set or clear the checkmark for each menu item since the selection
+ // may be in a new location from where it was when the menu was previously opened
+
+ // First 2 items add <small> and <big> tags
+ // While it would be better to show the number of levels,
+ // at least this tells user if either of them are set
+ var menuItem = children[0];
+ if (menuItem)
+ {
+ EditorGetTextProperty("small", "", "", firstHas, anyHas, allHas);
+ menuItem.setAttribute("checked", allHas.value);
+ sizeWasFound = anyHas.value;
+ }
+
+ menuItem = children[1];
+ if (menuItem)
+ {
+ EditorGetTextProperty("big", "", "", firstHas, anyHas, allHas);
+ menuItem.setAttribute("checked", allHas.value);
+ sizeWasFound |= anyHas.value;
+ }
+
+ // Fixed size items start after menu separator
+ var menuIndex = 3;
+ // Index of the medium (default) item
+ var mediumIndex = 5;
+
+ // Scan through all supported "font size" attribute values
+ for (var i = -2; i <= 3; i++)
+ {
+ menuItem = children[menuIndex];
+
+ // Skip over medium since it'll be set below.
+ // If font size=0 is actually set, we'll toggle it off below if
+ // we enter this loop in this case.
+ if (menuItem && (i != 0))
+ {
+ var sizeString = (i <= 0) ? String(i) : ("+" + String(i));
+ EditorGetTextProperty("font", "size", sizeString, firstHas, anyHas, allHas);
+ // Check the item only if all of selection has the size...
+ menuItem.setAttribute("checked", allHas.value);
+ // ...but remember if ANY of of selection had size set
+ sizeWasFound |= anyHas.value;
+ }
+ menuIndex++;
+ }
+
+ // if no size was found, then check default (medium)
+ // note that no item is checked in the case of "mixed" selection
+ children[mediumIndex].setAttribute("checked", !sizeWasFound);
+ }
+}
+
+function onHighlightColorChange()
+{
+ var commandNode = document.getElementById("cmd_highlight");
+ if (commandNode)
+ {
+ var color = commandNode.getAttribute("state");
+ var button = document.getElementById("HighlightColorButton");
+ if (button)
+ {
+ // No color set - get color set on page or other defaults
+ if (!color)
+ color = "transparent" ;
+
+ button.setAttribute("style", "background-color:"+color+" !important");
+ }
+ }
+}
+
+function onFontColorChange()
+{
+ var commandNode = document.getElementById("cmd_fontColor");
+ if (commandNode)
+ {
+ var color = commandNode.getAttribute("state");
+ var button = document.getElementById("TextColorButton");
+ if (button)
+ {
+ // No color set - get color set on page or other defaults
+ if (!color)
+ color = gDefaultTextColor;
+ button.setAttribute("style", "background-color:"+color);
+ }
+ }
+}
+
+function onBackgroundColorChange()
+{
+ var commandNode = document.getElementById("cmd_backgroundColor");
+ if (commandNode)
+ {
+ var color = commandNode.getAttribute("state");
+ var button = document.getElementById("BackgroundColorButton");
+ if (button)
+ {
+ if (!color)
+ color = gDefaultBackgroundColor;
+
+ button.setAttribute("style", "background-color:"+color);
+ }
+ }
+}
+
+// Call this when user changes text and/or background colors of the page
+function UpdateDefaultColors()
+{
+ var BrowserColors = GetDefaultBrowserColors();
+ var bodyelement = GetBodyElement();
+ var defTextColor = gDefaultTextColor;
+ var defBackColor = gDefaultBackgroundColor;
+
+ if (bodyelement)
+ {
+ var color = bodyelement.getAttribute("text");
+ if (color)
+ gDefaultTextColor = color;
+ else if (BrowserColors)
+ gDefaultTextColor = BrowserColors.TextColor;
+
+ color = bodyelement.getAttribute("bgcolor");
+ if (color)
+ gDefaultBackgroundColor = color;
+ else if (BrowserColors)
+ gDefaultBackgroundColor = BrowserColors.BackgroundColor;
+ }
+
+ // Trigger update on toolbar
+ if (defTextColor != gDefaultTextColor)
+ {
+ goUpdateCommandState("cmd_fontColor");
+ onFontColorChange();
+ }
+ if (defBackColor != gDefaultBackgroundColor)
+ {
+ goUpdateCommandState("cmd_backgroundColor");
+ onBackgroundColorChange();
+ }
+}
+
+function GetBackgroundElementWithColor()
+{
+ var editor = GetCurrentTableEditor();
+ if (!editor)
+ return null;
+
+ gColorObj.Type = "";
+ gColorObj.PageColor = "";
+ gColorObj.TableColor = "";
+ gColorObj.CellColor = "";
+ gColorObj.BackgroundColor = "";
+ gColorObj.SelectedType = "";
+
+ var tagNameObj = { value: "" };
+ var element;
+ try {
+ element = editor.getSelectedOrParentTableElement(tagNameObj, {value:0});
+ }
+ catch(e) {}
+
+ if (element && tagNameObj && tagNameObj.value)
+ {
+ gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
+ gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
+ if (tagNameObj.value.toLowerCase() == "td")
+ {
+ gColorObj.Type = "Cell";
+ gColorObj.CellColor = gColorObj.BackgroundColor;
+
+ // Get any color that might be on parent table
+ var table = GetParentTable(element);
+ gColorObj.TableColor = GetHTMLOrCSSStyleValue(table, "bgcolor", "background-color");
+ gColorObj.TableColor = ConvertRGBColorIntoHEXColor(gColorObj.TableColor);
+ }
+ else
+ {
+ gColorObj.Type = "Table";
+ gColorObj.TableColor = gColorObj.BackgroundColor;
+ }
+ gColorObj.SelectedType = gColorObj.Type;
+ }
+ else
+ {
+ var IsCSSPrefChecked = gPrefs.getBoolPref(kUseCssPref);
+ if (IsCSSPrefChecked && IsHTMLEditor())
+ {
+ var selection = editor.selection;
+ if (selection)
+ {
+ element = selection.focusNode;
+ while (!editor.nodeIsBlock(element))
+ element = element.parentNode;
+ }
+ else
+ {
+ element = GetBodyElement();
+ }
+ }
+ else
+ {
+ element = GetBodyElement();
+ }
+ if (element)
+ {
+ gColorObj.Type = "Page";
+ gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
+ if (gColorObj.BackgroundColor == "")
+ {
+ gColorObj.BackgroundColor = "transparent";
+ }
+ else
+ {
+ gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
+ }
+ gColorObj.PageColor = gColorObj.BackgroundColor;
+ }
+ }
+ return element;
+}
+
+function SetSmiley(smileyText)
+{
+ try {
+ GetCurrentEditor().insertText(smileyText);
+ gContentWindow.focus();
+ }
+ catch(e) {}
+}
+
+function EditorSelectColor(colorType, mouseEvent)
+{
+ var editor = GetCurrentEditor();
+ if (!editor || !gColorObj)
+ return;
+
+ // Shift + mouse click automatically applies last color, if available
+ var useLastColor = mouseEvent ? ( mouseEvent.button == 0 && mouseEvent.shiftKey ) : false;
+ var element;
+ var table;
+ var currentColor = "";
+ var commandNode;
+
+ if (!colorType)
+ colorType = "";
+
+ if (colorType == "Text")
+ {
+ gColorObj.Type = colorType;
+
+ // Get color from command node state
+ commandNode = document.getElementById("cmd_fontColor");
+ currentColor = commandNode.getAttribute("state");
+ currentColor = ConvertRGBColorIntoHEXColor(currentColor);
+ gColorObj.TextColor = currentColor;
+
+ if (useLastColor && gColorObj.LastTextColor )
+ gColorObj.TextColor = gColorObj.LastTextColor;
+ else
+ useLastColor = false;
+ }
+ else if (colorType == "Highlight")
+ {
+ gColorObj.Type = colorType;
+
+ // Get color from command node state
+ commandNode = document.getElementById("cmd_highlight");
+ currentColor = commandNode.getAttribute("state");
+ currentColor = ConvertRGBColorIntoHEXColor(currentColor);
+ gColorObj.HighlightColor = currentColor;
+
+ if (useLastColor && gColorObj.LastHighlightColor )
+ gColorObj.HighlightColor = gColorObj.LastHighlightColor;
+ else
+ useLastColor = false;
+ }
+ else
+ {
+ element = GetBackgroundElementWithColor();
+ if (!element)
+ return;
+
+ // Get the table if we found a cell
+ if (gColorObj.Type == "Table")
+ table = element;
+ else if (gColorObj.Type == "Cell")
+ table = GetParentTable(element);
+
+ // Save to avoid resetting if not necessary
+ currentColor = gColorObj.BackgroundColor;
+
+ if (colorType == "TableOrCell" || colorType == "Cell")
+ {
+ if (gColorObj.Type == "Cell")
+ gColorObj.Type = colorType;
+ else if (gColorObj.Type != "Table")
+ return;
+ }
+ else if (colorType == "Table" && gColorObj.Type == "Page")
+ return;
+
+ if (colorType == "" && gColorObj.Type == "Cell")
+ {
+ // Using empty string for requested type means
+ // we can let user select cell or table
+ gColorObj.Type = "TableOrCell";
+ }
+
+ if (useLastColor && gColorObj.LastBackgroundColor )
+ gColorObj.BackgroundColor = gColorObj.LastBackgroundColor;
+ else
+ useLastColor = false;
+ }
+ // Save the type we are really requesting
+ colorType = gColorObj.Type;
+
+ if (!useLastColor)
+ {
+ // Avoid the JS warning
+ gColorObj.NoDefault = false;
+
+ // Launch the ColorPicker dialog
+ // TODO: Figure out how to position this under the color buttons on the toolbar
+ window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", gColorObj);
+
+ // User canceled the dialog
+ if (gColorObj.Cancel)
+ return;
+ }
+
+ if (gColorObj.Type == "Text")
+ {
+ if (currentColor != gColorObj.TextColor)
+ {
+ if (gColorObj.TextColor)
+ EditorSetTextProperty("font", "color", gColorObj.TextColor);
+ else
+ EditorRemoveTextProperty("font", "color");
+ }
+ // Update the command state (this will trigger color button update)
+ goUpdateCommandState("cmd_fontColor");
+ }
+ else if (gColorObj.Type == "Highlight")
+ {
+ if (currentColor != gColorObj.HighlightColor)
+ {
+ if (gColorObj.HighlightColor)
+ EditorSetTextProperty("font", "bgcolor", gColorObj.HighlightColor);
+ else
+ EditorRemoveTextProperty("font", "bgcolor");
+ }
+ // Update the command state (this will trigger color button update)
+ goUpdateCommandState("cmd_highlight");
+ }
+ else if (element)
+ {
+ if (gColorObj.Type == "Table")
+ {
+ // Set background on a table
+ // Note that we shouldn't trust "currentColor" because of "TableOrCell" behavior
+ if (table)
+ {
+ var bgcolor = table.getAttribute("bgcolor");
+ if (bgcolor != gColorObj.BackgroundColor)
+ try {
+ if (gColorObj.BackgroundColor)
+ editor.setAttributeOrEquivalent(table, "bgcolor", gColorObj.BackgroundColor, false);
+ else
+ editor.removeAttributeOrEquivalent(table, "bgcolor", false);
+ } catch (e) {}
+ }
+ }
+ else if (currentColor != gColorObj.BackgroundColor && IsHTMLEditor())
+ {
+ editor.beginTransaction();
+ try
+ {
+ editor.setBackgroundColor(gColorObj.BackgroundColor);
+
+ if (gColorObj.Type == "Page" && gColorObj.BackgroundColor)
+ {
+ // Set all page colors not explicitly set,
+ // else you can end up with unreadable pages
+ // because viewer's default colors may not be same as page author's
+ var bodyelement = GetBodyElement();
+ if (bodyelement)
+ {
+ var defColors = GetDefaultBrowserColors();
+ if (defColors)
+ {
+ if (!bodyelement.getAttribute("text"))
+ editor.setAttributeOrEquivalent(bodyelement, "text", defColors.TextColor, false);
+
+ // The following attributes have no individual CSS declaration counterparts
+ // Getting rid of them in favor of CSS implies CSS rules management
+ if (!bodyelement.getAttribute("link"))
+ editor.setAttribute(bodyelement, "link", defColors.LinkColor);
+
+ if (!bodyelement.getAttribute("alink"))
+ editor.setAttribute(bodyelement, "alink", defColors.ActiveLinkColor);
+
+ if (!bodyelement.getAttribute("vlink"))
+ editor.setAttribute(bodyelement, "vlink", defColors.VisitedLinkColor);
+ }
+ }
+ }
+ }
+ catch(e) {}
+
+ editor.endTransaction();
+ }
+
+ goUpdateCommandState("cmd_backgroundColor");
+ }
+ gContentWindow.focus();
+}
+
+function GetParentTable(element)
+{
+ var node = element;
+ while (node)
+ {
+ if (node.nodeName.toLowerCase() == "table")
+ return node;
+
+ node = node.parentNode;
+ }
+ return node;
+}
+
+function GetParentTableCell(element)
+{
+ var node = element;
+ while (node)
+ {
+ if (node.nodeName.toLowerCase() == "td" || node.nodeName.toLowerCase() == "th")
+ return node;
+
+ node = node.parentNode;
+ }
+ return node;
+}
+
+function EditorDblClick(event)
+{
+ // We check event.explicitOriginalTarget here because .target will never
+ // be a textnode (bug 193689)
+ if (event.explicitOriginalTarget)
+ {
+ // Only bring up properties if clicked on an element or selected link
+ var element;
+ try {
+ element = event.explicitOriginalTarget.QueryInterface(
+ Components.interfaces.nsIDOMElement);
+ } catch (e) {}
+
+ // We use "href" instead of "a" to not be fooled by named anchor
+ if (!element)
+ try {
+ element = GetCurrentEditor().getSelectedElement("href");
+ } catch (e) {}
+
+ if (element)
+ {
+ goDoCommand("cmd_objectProperties");
+ event.preventDefault();
+ }
+ }
+}
+
+function EditorClick(event)
+{
+ if (!event)
+ return;
+
+ if (event.detail == 2)
+ {
+ EditorDblClick(event);
+ return;
+ }
+
+ // For Web Composer: In Show All Tags Mode,
+ // single click selects entire element,
+ // except for body and table elements
+ if (IsWebComposer() && event.explicitOriginalTarget && IsHTMLEditor() &&
+ gEditorDisplayMode == kDisplayModeAllTags)
+ {
+ try
+ {
+ // We check event.explicitOriginalTarget here because .target will never
+ // be a textnode (bug 193689)
+ var element = event.explicitOriginalTarget.QueryInterface(
+ Components.interfaces.nsIDOMElement);
+ var name = element.localName.toLowerCase();
+ if (name != "body" && name != "table" &&
+ name != "td" && name != "th" && name != "caption" && name != "tr")
+ {
+ GetCurrentEditor().selectElement(event.explicitOriginalTarget);
+ event.preventDefault();
+ }
+ } catch (e) {}
+ }
+}
+
+/*TODO: We need an oncreate hook to do enabling/disabling for the
+ Format menu. There should be code like this for the
+ object-specific "Properties" item
+*/
+// For property dialogs, we want the selected element,
+// but will accept a parent link, list, or table cell if inside one
+function GetObjectForProperties()
+{
+ var editor = GetCurrentEditor();
+ if (!editor || !IsHTMLEditor())
+ return null;
+
+ var element;
+ try {
+ element = editor.getSelectedElement("");
+ } catch (e) {}
+ if (element)
+ return element;
+
+ // Find nearest parent of selection anchor node
+ // that is a link, list, table cell, or table
+
+ var anchorNode
+ var node;
+ try {
+ anchorNode = editor.selection.anchorNode;
+ if (anchorNode.firstChild)
+ {
+ // Start at actual selected node
+ var offset = editor.selection.anchorOffset;
+ // Note: If collapsed, offset points to element AFTER caret,
+ // thus node may be null
+ node = anchorNode.childNodes.item(offset);
+ }
+ if (!node)
+ node = anchorNode;
+ } catch (e) {}
+
+ while (node)
+ {
+ if (node.nodeName)
+ {
+ var nodeName = node.nodeName.toLowerCase();
+
+ // Done when we hit the body
+ if (nodeName == "body") break;
+
+ if ((nodeName == "a" && node.href) ||
+ nodeName == "ol" || nodeName == "ul" || nodeName == "dl" ||
+ nodeName == "td" || nodeName == "th" ||
+ nodeName == "table")
+ {
+ return node;
+ }
+ }
+ node = node.parentNode;
+ }
+ return null;
+}
+
+function SetEditMode(mode)
+{
+ if (!IsHTMLEditor())
+ return;
+
+ var bodyElement = GetBodyElement();
+ if (!bodyElement)
+ {
+ dump("SetEditMode: We don't have a body node!\n");
+ return;
+ }
+
+ // must have editor if here!
+ var editor = GetCurrentEditor();
+ var inlineSpellCheckItem = document.getElementById('menu_inlinespellcheck');
+
+ // Switch the UI mode before inserting contents
+ // so user can't type in source window while new window is being filled
+ var previousMode = gEditorDisplayMode;
+ if (!SetDisplayMode(mode))
+ return;
+
+ if (mode == kDisplayModeSource)
+ {
+ // Display the DOCTYPE as a non-editable string above edit area
+ var domdoc;
+ try { domdoc = editor.document; } catch (e) { dump( e + "\n");}
+ if (domdoc)
+ {
+ var doctypeNode = document.getElementById("doctype-text");
+ var dt = domdoc.doctype;
+ if (doctypeNode)
+ {
+ if (dt)
+ {
+ doctypeNode.collapsed = false;
+ var doctypeText = "<!DOCTYPE " + domdoc.doctype.name;
+ if (dt.publicId)
+ doctypeText += " PUBLIC \"" + domdoc.doctype.publicId;
+ if (dt.systemId)
+ doctypeText += " "+"\"" + dt.systemId;
+ doctypeText += "\">"
+ doctypeNode.setAttribute("value", doctypeText);
+ }
+ else
+ doctypeNode.collapsed = true;
+ }
+ }
+ // Get the entire document's source string
+
+ var flags = (editor.documentCharacterSet == "ISO-8859-1")
+ ? kOutputEncodeLatin1Entities
+ : kOutputEncodeBasicEntities;
+ try {
+ var encodeEntity = gPrefs.getCharPref("editor.encode_entity");
+ switch (encodeEntity) {
+ case "basic" : flags = kOutputEncodeBasicEntities; break;
+ case "latin1" : flags = kOutputEncodeLatin1Entities; break;
+ case "html" : flags = kOutputEncodeHTMLEntities; break;
+ case "none" : flags = 0; break;
+ }
+ } catch (e) { }
+
+ try {
+ var prettyPrint = gPrefs.getBoolPref("editor.prettyprint");
+ if (prettyPrint)
+ flags |= kOutputFormatted;
+
+ } catch (e) {}
+
+ flags |= kOutputLFLineBreak;
+ var source = editor.outputToString(kHTMLMimeType, flags);
+ var start = source.search(/<html/i);
+ if (start == -1) start = 0;
+ gSourceTextEditor.insertText(source.slice(start));
+ gSourceTextEditor.resetModificationCount();
+ gSourceTextEditor.addDocumentStateListener(gSourceTextListener);
+ gSourceTextEditor.enableUndo(true);
+ gSourceContentWindow.commandManager.addCommandObserver(gSourceTextObserver, "cmd_undo");
+ gSourceContentWindow.contentWindow.focus();
+ goDoCommand("cmd_moveTop");
+ }
+ else if (previousMode == kDisplayModeSource)
+ {
+ // Only rebuild document if a change was made in source window
+ if (IsHTMLSourceChanged())
+ {
+ // Disable spell checking when rebuilding source
+ InlineSpellCheckerUI.enabled = false;
+ inlineSpellCheckItem.removeAttribute('checked');
+
+ // Reduce the undo count so we don't use too much memory
+ // during multiple uses of source window
+ // (reinserting entire doc caches all nodes)
+ try {
+ editor.transactionManager.maxTransactionCount = 1;
+ } catch (e) {}
+
+ editor.beginTransaction();
+ try {
+ // We are coming from edit source mode,
+ // so transfer that back into the document
+ source = gSourceTextEditor.outputToString(kTextMimeType, kOutputLFLineBreak);
+ editor.rebuildDocumentFromSource(source);
+
+ // Get the text for the <title> from the newly-parsed document
+ // (must do this for proper conversion of "escaped" characters)
+ var title = "";
+ var titlenodelist = editor.document.getElementsByTagName("title");
+ if (titlenodelist)
+ {
+ var titleNode = titlenodelist.item(0);
+ if (titleNode && titleNode.firstChild && titleNode.firstChild.data)
+ title = titleNode.firstChild.data;
+ }
+ if (editor.document.title != title)
+ SetDocumentTitle(title);
+
+ } catch (ex) {
+ dump(ex);
+ }
+ editor.endTransaction();
+
+ // Restore unlimited undo count
+ try {
+ editor.transactionManager.maxTransactionCount = -1;
+ } catch (e) {}
+ }
+
+ // Clear out the string buffers
+ gSourceContentWindow.commandManager.removeCommandObserver(gSourceTextObserver, "cmd_undo");
+ gSourceTextEditor.removeDocumentStateListener(gSourceTextListener);
+ gSourceTextEditor.enableUndo(false);
+ gSourceTextEditor.selectAll();
+ gSourceTextEditor.deleteSelection(gSourceTextEditor.eNone);
+ gSourceTextEditor.resetModificationCount();
+
+ gContentWindow.focus();
+ }
+
+ switch (mode) {
+ case kDisplayModePreview:
+ // Disable spell checking when previewing
+ InlineSpellCheckerUI.enabled = false;
+ inlineSpellCheckItem.removeAttribute('checked');
+ // fall through
+ case kDisplayModeSource:
+ inlineSpellCheckItem.setAttribute('disabled', 'true');
+ break;
+ default:
+ inlineSpellCheckItem.setAttribute('disabled', !InlineSpellCheckerUI.canSpellCheck);
+ break;
+ }
+}
+
+function CancelHTMLSource()
+{
+ // Don't convert source text back into the DOM document
+ gSourceTextEditor.resetModificationCount();
+ SetDisplayMode(gPreviousNonSourceDisplayMode);
+}
+
+function FinishHTMLSource()
+{
+ //Here we need to check whether the HTML source contains <head> and <body> tags
+ //Or RebuildDocumentFromSource() will fail.
+ if (IsInHTMLSourceMode())
+ {
+ var htmlSource = gSourceTextEditor.outputToString(kTextMimeType, kOutputLFLineBreak);
+ if (htmlSource.length > 0)
+ {
+ var beginHead = htmlSource.indexOf("<head");
+ if (beginHead == -1)
+ {
+ AlertWithTitle(GetString("Alert"), GetString("NoHeadTag"));
+ //cheat to force back to Source Mode
+ gEditorDisplayMode = kDisplayModePreview;
+ SetDisplayMode(kDisplayModeSource);
+ throw Components.results.NS_ERROR_FAILURE;
+ }
+
+ var beginBody = htmlSource.indexOf("<body");
+ if (beginBody == -1)
+ {
+ AlertWithTitle(GetString("Alert"), GetString("NoBodyTag"));
+ //cheat to force back to Source Mode
+ gEditorDisplayMode = kDisplayModePreview;
+ SetDisplayMode(kDisplayModeSource);
+ throw Components.results.NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ // Switch edit modes -- converts source back into DOM document
+ SetEditMode(gPreviousNonSourceDisplayMode);
+}
+
+function SetDisplayMode(mode)
+{
+ if (!IsHTMLEditor())
+ return false;
+
+ // Already in requested mode:
+ // return false to indicate we didn't switch
+ if (mode == gEditorDisplayMode)
+ return false;
+
+ var previousMode = gEditorDisplayMode;
+ gEditorDisplayMode = mode;
+
+ ResetStructToolbar();
+ if (mode == kDisplayModeSource)
+ {
+ // Switch to the sourceWindow (second in the deck)
+ gContentWindowDeck.selectedIndex = 1;
+
+ //Hide the formatting toolbar if not already hidden
+ gFormatToolbarHidden = gFormatToolbar.hidden;
+ gFormatToolbar.hidden = true;
+ gViewFormatToolbar.hidden = true;
+
+ gSourceContentWindow.contentWindow.focus();
+ }
+ else
+ {
+ // Save the last non-source mode so we can cancel source editing easily
+ gPreviousNonSourceDisplayMode = mode;
+
+ // Load/unload appropriate override style sheet
+ try {
+ var editor = GetCurrentEditor();
+ editor.QueryInterface(nsIEditorStyleSheets);
+ editor instanceof Components.interfaces.nsIHTMLObjectResizer;
+
+ switch (mode)
+ {
+ case kDisplayModePreview:
+ // Disable all extra "edit mode" style sheets
+ editor.enableStyleSheet(kNormalStyleSheet, false);
+ editor.enableStyleSheet(kAllTagsStyleSheet, false);
+ editor.isImageResizingEnabled = true;
+ break;
+
+ case kDisplayModeNormal:
+ editor.addOverrideStyleSheet(kNormalStyleSheet);
+ // Disable ShowAllTags mode
+ editor.enableStyleSheet(kAllTagsStyleSheet, false);
+ editor.isImageResizingEnabled = true;
+ break;
+
+ case kDisplayModeAllTags:
+ editor.addOverrideStyleSheet(kNormalStyleSheet);
+ editor.addOverrideStyleSheet(kAllTagsStyleSheet);
+ // don't allow resizing in AllTags mode because the visible tags
+ // change the computed size of images and tables...
+ if (editor.resizedObject) {
+ editor.hideResizers();
+ }
+ editor.isImageResizingEnabled = false;
+ break;
+ }
+ } catch(e) {}
+
+ // Switch to the normal editor (first in the deck)
+ gContentWindowDeck.selectedIndex = 0;
+
+ // Restore menus and toolbars
+ gFormatToolbar.hidden = gFormatToolbarHidden;
+ gViewFormatToolbar.hidden = false;
+
+ gContentWindow.focus();
+ }
+
+ // update commands to disable or re-enable stuff
+ window.updateCommands("mode_switch");
+
+ // Set the selected tab at bottom of window:
+ // (Note: Setting "selectedIndex = mode" won't redraw tabs when menu is used.)
+ document.getElementById("EditModeTabs").selectedItem = document.getElementById(kDisplayModeTabIDS[mode]);
+
+ // Uncheck previous menuitem and set new check since toolbar may have been used
+ if (previousMode >= 0)
+ document.getElementById(kDisplayModeMenuIDs[previousMode]).setAttribute("checked","false");
+ document.getElementById(kDisplayModeMenuIDs[mode]).setAttribute("checked","true");
+
+
+ return true;
+}
+
+function EditorToggleParagraphMarks()
+{
+ var menuItem = document.getElementById("viewParagraphMarks");
+ if (menuItem)
+ {
+ // Note that the 'type="checbox"' mechanism automatically
+ // toggles the "checked" state before the oncommand is called,
+ // so if "checked" is true now, it was just switched to that mode
+ var checked = menuItem.getAttribute("checked");
+ try {
+ var editor = GetCurrentEditor();
+ editor.QueryInterface(nsIEditorStyleSheets);
+
+ if (checked == "true")
+ editor.addOverrideStyleSheet(kParagraphMarksStyleSheet);
+ else
+ editor.enableStyleSheet(kParagraphMarksStyleSheet, false);
+ }
+ catch(e) { return; }
+ }
+}
+
+function InitPasteAsMenu()
+{
+ var menuItem = document.getElementById("menu_pasteTable")
+ if(menuItem)
+ {
+ menuItem.IsInTable
+ menuItem.setAttribute("label", GetString(IsInTable() ? "NestedTable" : "Table"));
+ // menuItem.setAttribute("accesskey",GetString("ObjectPropertiesAccessKey"));
+ }
+ // TODO: Do enabling based on what is in the clipboard
+}
+
+function UpdateWindowTitle()
+{
+ try {
+ var windowTitle = GetDocumentTitle();
+ if (!windowTitle)
+ windowTitle = GetString("untitled");
+
+ // Append just the 'leaf' filename to the Doc. Title for the window caption
+ var docUrl = GetDocumentUrl();
+ if (docUrl && !IsUrlAboutBlank(docUrl))
+ {
+ var scheme = GetScheme(docUrl);
+ var filename = GetFilename(docUrl);
+ if (filename)
+ windowTitle += " [" + scheme + ":/.../" + filename + "]";
+
+ // Save changed title in the recent pages data in prefs
+ SaveRecentFilesPrefs();
+ }
+ // Set window title with " - Composer" appended
+ var xulWin = document.documentElement;
+ document.title = windowTitle + xulWin.getAttribute("titlemenuseparator") +
+ xulWin.getAttribute("titlemodifier");
+ } catch (e) { dump(e); }
+}
+
+function BuildRecentPagesMenu()
+{
+ var editor = GetCurrentEditor();
+ if (!editor || !gPrefs)
+ return;
+
+ var popup = document.getElementById("menupopup_RecentFiles");
+ if (!popup || !editor.document)
+ return;
+
+ // Delete existing menu
+ while (popup.firstChild)
+ popup.removeChild(popup.firstChild);
+
+ // Current page is the "0" item in the list we save in prefs,
+ // but we don't include it in the menu.
+ var curUrl = StripPassword(GetDocumentUrl());
+ var historyCount = 10;
+ try {
+ historyCount = gPrefs.getIntPref("editor.history.url_maximum");
+ } catch(e) {}
+ var menuIndex = 1;
+
+ for (var i = 0; i < historyCount; i++)
+ {
+ var url = GetUnicharPref("editor.history_url_"+i);
+
+ // Skip over current url
+ if (url && url != curUrl)
+ {
+ // Build the menu
+ var title = GetUnicharPref("editor.history_title_"+i);
+ AppendRecentMenuitem(popup, title, url, menuIndex);
+ menuIndex++;
+ }
+ }
+}
+
+function SaveRecentFilesPrefs()
+{
+ // Can't do anything if no prefs
+ if (!gPrefs) return;
+
+ var curUrl = StripPassword(GetDocumentUrl());
+ var historyCount = 10;
+ try {
+ historyCount = gPrefs.getIntPref("editor.history.url_maximum");
+ } catch(e) {}
+
+ var titleArray = [];
+ var urlArray = [];
+
+ if (historyCount && !IsUrlAboutBlank(curUrl) && GetScheme(curUrl) != "data")
+ {
+ titleArray.push(GetDocumentTitle());
+ urlArray.push(curUrl);
+ }
+
+ for (var i = 0; i < historyCount && urlArray.length < historyCount; i++)
+ {
+ var url = GetUnicharPref("editor.history_url_"+i);
+
+ // Continue if URL pref is missing because
+ // a URL not found during loading may have been removed
+
+ // Skip over current an "data" URLs
+ if (url && url != curUrl && GetScheme(url) != "data")
+ {
+ var title = GetUnicharPref("editor.history_title_"+i);
+ titleArray.push(title);
+ urlArray.push(url);
+ }
+ }
+
+ // Resave the list back to prefs in the new order
+ for (i = 0; i < urlArray.length; i++)
+ {
+ SetUnicharPref("editor.history_title_"+i, titleArray[i]);
+ SetUnicharPref("editor.history_url_"+i, urlArray[i]);
+ }
+}
+
+function AppendRecentMenuitem(menupopup, title, url, menuIndex)
+{
+ if (menupopup)
+ {
+ var menuItem = document.createElementNS(XUL_NS, "menuitem");
+ if (menuItem)
+ {
+ var accessKey;
+ if (menuIndex <= 9)
+ accessKey = String(menuIndex);
+ else if (menuIndex == 10)
+ accessKey = "0";
+ else
+ accessKey = " ";
+
+ var itemString = accessKey+" ";
+
+ // Show "title [url]" or just the URL
+ if (title)
+ {
+ itemString += title;
+ itemString += " [";
+ }
+ itemString += url;
+ if (title)
+ itemString += "]";
+
+ menuItem.setAttribute("label", itemString);
+ menuItem.setAttribute("crop", "center");
+ menuItem.setAttribute("value", url);
+ if (accessKey != " ")
+ menuItem.setAttribute("accesskey", accessKey);
+ menupopup.appendChild(menuItem);
+ }
+ }
+}
+
+function EditorInitFileMenu()
+{
+ // Disable "Save" menuitem when editing remote url. User should use "Save As"
+ var docUrl = GetDocumentUrl();
+ var scheme = GetScheme(docUrl);
+ if (scheme && scheme != "file")
+ SetElementEnabledById("saveMenuitem", false);
+
+ // Enable recent pages submenu if there are any history entries in prefs
+ var historyUrl = "";
+
+ var historyCount = 10;
+ try { historyCount = gPrefs.getIntPref("editor.history.url_maximum"); } catch(e) {}
+ if (historyCount)
+ {
+ historyUrl = GetUnicharPref("editor.history_url_0");
+
+ // See if there's more if current file is only entry in history list
+ if (historyUrl && historyUrl == docUrl)
+ historyUrl = GetUnicharPref("editor.history_url_1");
+ }
+ SetElementEnabledById("menu_RecentFiles", historyUrl != "");
+}
+
+function EditorInitFormatMenu()
+{
+ try {
+ InitObjectPropertiesMenuitem("objectProperties");
+ InitRemoveStylesMenuitems("removeStylesMenuitem", "removeLinksMenuitem", "removeNamedAnchorsMenuitem");
+ } catch(ex) {}
+}
+
+function InitObjectPropertiesMenuitem(id)
+{
+ // Set strings and enable for the [Object] Properties item
+ // Note that we directly do the enabling instead of
+ // using goSetCommandEnabled since we already have the menuitem
+ var menuItem = document.getElementById(id);
+ if (!menuItem) return null;
+
+ var element;
+ var menuStr = GetString("AdvancedProperties");
+ var name;
+
+ if (IsEditingRenderedHTML())
+ element = GetObjectForProperties();
+
+ if (element && element.nodeName)
+ {
+ var objStr = "";
+ menuItem.setAttribute("disabled", "");
+ name = element.nodeName.toLowerCase();
+ switch (name)
+ {
+ case "img":
+ // Check if img is enclosed in link
+ // (use "href" to not be fooled by named anchor)
+ try
+ {
+ if (GetCurrentEditor().getElementOrParentByTagName("href", element))
+ objStr = GetString("ImageAndLink");
+ } catch(e) {}
+
+ if (objStr == "")
+ objStr = GetString("Image");
+ break;
+ case "hr":
+ objStr = GetString("HLine");
+ break;
+ case "table":
+ objStr = GetString("Table");
+ break;
+ case "th":
+ name = "td";
+ case "td":
+ objStr = GetString("TableCell");
+ break;
+ case "ol":
+ case "ul":
+ case "dl":
+ objStr = GetString("List");
+ break;
+ case "li":
+ objStr = GetString("ListItem");
+ break;
+ case "form":
+ objStr = GetString("Form");
+ break;
+ case "input":
+ var type = element.getAttribute("type");
+ if (type && type.toLowerCase() == "image")
+ objStr = GetString("InputImage");
+ else
+ objStr = GetString("InputTag");
+ break;
+ case "textarea":
+ objStr = GetString("TextArea");
+ break;
+ case "select":
+ objStr = GetString("Select");
+ break;
+ case "button":
+ objStr = GetString("Button");
+ break;
+ case "label":
+ objStr = GetString("Label");
+ break;
+ case "fieldset":
+ objStr = GetString("FieldSet");
+ break;
+ case "a":
+ if (element.name)
+ {
+ objStr = GetString("NamedAnchor");
+ name = "anchor";
+ }
+ else if(element.href)
+ {
+ objStr = GetString("Link");
+ name = "href";
+ }
+ break;
+ }
+ if (objStr)
+ menuStr = GetString("ObjectProperties").replace(/%obj%/,objStr);
+ }
+ else
+ {
+ // We show generic "Properties" string, but disable menu item
+ menuItem.setAttribute("disabled","true");
+ }
+ menuItem.setAttribute("label", menuStr);
+ menuItem.setAttribute("accesskey",GetString("ObjectPropertiesAccessKey"));
+ return name;
+}
+
+function InitParagraphMenu()
+{
+ var mixedObj = { value: null };
+ var state;
+ try {
+ state = GetCurrentEditor().getParagraphState(mixedObj);
+ }
+ catch(e) {}
+ var IDSuffix;
+
+ // PROBLEM: When we get blockquote, it masks other styles contained by it
+ // We need a separate method to get blockquote state
+
+ // We use "x" as uninitialized paragraph state
+ if (!state || state == "x")
+ IDSuffix = "bodyText" // No paragraph container
+ else
+ IDSuffix = state;
+
+ // Set "radio" check on one item, but...
+ var menuItem = document.getElementById("menu_"+IDSuffix);
+ menuItem.setAttribute("checked", "true");
+
+ // ..."bodyText" is returned if mixed selection, so remove checkmark
+ if (mixedObj.value)
+ menuItem.setAttribute("checked", "false");
+}
+
+function GetListStateString()
+{
+ try {
+ var editor = GetCurrentEditor();
+
+ var mixedObj = { value: null };
+ var hasOL = { value: false };
+ var hasUL = { value: false };
+ var hasDL = { value: false };
+ editor.getListState(mixedObj, hasOL, hasUL, hasDL);
+
+ if (mixedObj.value)
+ return "mixed";
+ if (hasOL.value)
+ return "ol";
+ if (hasUL.value)
+ return "ul";
+
+ if (hasDL.value)
+ {
+ var hasLI = { value: false };
+ var hasDT = { value: false };
+ var hasDD = { value: false };
+ editor.getListItemState(mixedObj, hasLI, hasDT, hasDD);
+ if (mixedObj.value)
+ return "mixed";
+ if (hasLI.value)
+ return "li";
+ if (hasDT.value)
+ return "dt";
+ if (hasDD.value)
+ return "dd";
+ }
+ } catch (e) {}
+
+ // return "noList" if we aren't in a list at all
+ return "noList";
+}
+
+function InitListMenu()
+{
+ if (!IsHTMLEditor())
+ return;
+
+ var IDSuffix = GetListStateString();
+
+ // Set enable state for the "None" menuitem
+ goSetCommandEnabled("cmd_removeList", IDSuffix != "noList");
+
+ // Set "radio" check on one item, but...
+ // we won't find a match if it's "mixed"
+ var menuItem = document.getElementById("menu_"+IDSuffix);
+ if (menuItem)
+ menuItem.setAttribute("checked", "true");
+}
+
+function GetAlignmentString()
+{
+ var mixedObj = { value: null };
+ var alignObj = { value: null };
+ try {
+ GetCurrentEditor().getAlignment(mixedObj, alignObj);
+ } catch (e) {}
+
+ if (mixedObj.value)
+ return "mixed";
+ if (alignObj.value == nsIHTMLEditor.eLeft)
+ return "left";
+ if (alignObj.value == nsIHTMLEditor.eCenter)
+ return "center";
+ if (alignObj.value == nsIHTMLEditor.eRight)
+ return "right";
+ if (alignObj.value == nsIHTMLEditor.eJustify)
+ return "justify";
+
+ // return "left" if we got here
+ return "left";
+}
+
+function InitAlignMenu()
+{
+ if (!IsHTMLEditor())
+ return;
+
+ var IDSuffix = GetAlignmentString();
+
+ // we won't find a match if it's "mixed"
+ var menuItem = document.getElementById("menu_"+IDSuffix);
+ if (menuItem)
+ menuItem.setAttribute("checked", "true");
+}
+
+function EditorSetDefaultPrefsAndDoctype()
+{
+ var editor = GetCurrentEditor();
+
+ var domdoc;
+ try {
+ domdoc = editor.document;
+ } catch (e) { dump( e + "\n"); }
+ if ( !domdoc )
+ {
+ dump("EditorSetDefaultPrefsAndDoctype: EDITOR DOCUMENT NOT FOUND\n");
+ return;
+ }
+
+ // Insert a doctype element
+ // if it is missing from existing doc
+ if (!domdoc.doctype)
+ {
+ var newdoctype = domdoc.implementation.createDocumentType("HTML", "-//W3C//DTD HTML 4.01 Transitional//EN","");
+ if (newdoctype)
+ domdoc.insertBefore(newdoctype, domdoc.firstChild);
+ }
+
+ // search for head; we'll need this for meta tag additions
+ var headelement = 0;
+ var headnodelist = domdoc.getElementsByTagName("head");
+ if (headnodelist)
+ {
+ var sz = headnodelist.length;
+ if ( sz >= 1 )
+ headelement = headnodelist.item(0);
+ }
+ else
+ {
+ headelement = domdoc.createElement("head");
+ if (headelement)
+ domdoc.insertAfter(headelement, domdoc.firstChild);
+ }
+
+ /* only set default prefs for new documents */
+ if (!IsUrlAboutBlank(GetDocumentUrl()))
+ return;
+
+ // search for author meta tag.
+ // if one is found, don't do anything.
+ // if not, create one and make it a child of the head tag
+ // and set its content attribute to the value of the editor.author preference.
+
+ var nodelist = domdoc.getElementsByTagName("meta");
+ if ( nodelist )
+ {
+ // we should do charset first since we need to have charset before
+ // hitting other 8-bit char in other meta tags
+ // grab charset pref and make it the default charset
+ var element;
+ var prefCharsetString = 0;
+ try
+ {
+ prefCharsetString = gPrefs.getComplexValue("intl.charset.default",
+ Components.interfaces.nsIPrefLocalizedString).data;
+ }
+ catch (ex) {}
+ if ( prefCharsetString && prefCharsetString != 0)
+ {
+ editor.enableUndo(false);
+ editor.documentCharacterSet = prefCharsetString;
+ editor.resetModificationCount();
+ editor.enableUndo(true);
+ }
+
+ var node = 0;
+ var listlength = nodelist.length;
+
+ // let's start by assuming we have an author in case we don't have the pref
+ var authorFound = false;
+ for (var i = 0; i < listlength && !authorFound; i++)
+ {
+ node = nodelist.item(i);
+ if ( node )
+ {
+ var value = node.getAttribute("name");
+ if (value && value.toLowerCase() == "author")
+ {
+ authorFound = true;
+ }
+ }
+ }
+
+ var prefAuthorString = 0;
+ try
+ {
+ prefAuthorString = gPrefs.getComplexValue("editor.author",
+ Components.interfaces.nsISupportsString).data;
+ }
+ catch (ex) {}
+ if ( prefAuthorString && prefAuthorString != 0)
+ {
+ if ( !authorFound && headelement)
+ {
+ /* create meta tag with 2 attributes */
+ element = domdoc.createElement("meta");
+ if ( element )
+ {
+ element.setAttribute("name", "author");
+ element.setAttribute("content", prefAuthorString);
+ headelement.appendChild( element );
+ }
+ }
+ }
+ }
+
+ // add title tag if not present
+ var titlenodelist = editor.document.getElementsByTagName("title");
+ if (headelement && titlenodelist && titlenodelist.length == 0)
+ {
+ titleElement = domdoc.createElement("title");
+ if (titleElement)
+ headelement.appendChild(titleElement);
+ }
+
+ // Get editor color prefs
+ var use_custom_colors = false;
+ try {
+ use_custom_colors = gPrefs.getBoolPref("editor.use_custom_colors");
+ }
+ catch (ex) {}
+
+ // find body node
+ var bodyelement = GetBodyElement();
+ if (bodyelement)
+ {
+ if ( use_custom_colors )
+ {
+ // try to get the default color values. ignore them if we don't have them.
+ var text_color;
+ var link_color;
+ var active_link_color;
+ var followed_link_color;
+ var background_color;
+
+ try { text_color = gPrefs.getCharPref("editor.text_color"); } catch (e) {}
+ try { link_color = gPrefs.getCharPref("editor.link_color"); } catch (e) {}
+ try { active_link_color = gPrefs.getCharPref("editor.active_link_color"); } catch (e) {}
+ try { followed_link_color = gPrefs.getCharPref("editor.followed_link_color"); } catch (e) {}
+ try { background_color = gPrefs.getCharPref("editor.background_color"); } catch(e) {}
+
+ // add the color attributes to the body tag.
+ // and use them for the default text and background colors if not empty
+ try {
+ if (text_color)
+ {
+ editor.setAttributeOrEquivalent(bodyelement, "text", text_color, true);
+ gDefaultTextColor = text_color;
+ }
+ if (background_color)
+ {
+ editor.setAttributeOrEquivalent(bodyelement, "bgcolor", background_color, true);
+ gDefaultBackgroundColor = background_color
+ }
+
+ if (link_color)
+ bodyelement.setAttribute("link", link_color);
+ if (active_link_color)
+ bodyelement.setAttribute("alink", active_link_color);
+ if (followed_link_color)
+ bodyelement.setAttribute("vlink", followed_link_color);
+ } catch (e) {}
+ }
+ // Default image is independent of Custom colors???
+ try {
+ var background_image = gPrefs.getCharPref("editor.default_background_image");
+ if (background_image)
+ editor.setAttributeOrEquivalent(bodyelement, "background", background_image, true);
+ } catch (e) {dump("BACKGROUND EXCEPTION: "+e+"\n"); }
+
+ }
+ // auto-save???
+}
+
+function GetBodyElement()
+{
+ try {
+ return GetCurrentEditor().rootElement;
+ }
+ catch (ex) {
+ dump("no body tag found?!\n");
+ // better have one, how can we blow things up here?
+ }
+ return null;
+}
+
+// --------------------------- Logging stuff ---------------------------
+
+function EditorGetNodeFromOffsets(offsets)
+{
+ var node = null;
+ try {
+ node = GetCurrentEditor().document;
+
+ for (var i = 0; i < offsets.length; i++)
+ node = node.childNodes[offsets[i]];
+ } catch (e) {}
+ return node;
+}
+
+function EditorSetSelectionFromOffsets(selRanges)
+{
+ try {
+ var editor = GetCurrentEditor();
+ var selection = editor.selection;
+ selection.removeAllRanges();
+
+ var rangeArr, start, end, node, offset;
+ for (var i = 0; i < selRanges.length; i++)
+ {
+ rangeArr = selRanges[i];
+ start = rangeArr[0];
+ end = rangeArr[1];
+
+ var range = editor.document.createRange();
+
+ node = EditorGetNodeFromOffsets(start[0]);
+ offset = start[1];
+
+ range.setStart(node, offset);
+
+ node = EditorGetNodeFromOffsets(end[0]);
+ offset = end[1];
+
+ range.setEnd(node, offset);
+
+ selection.addRange(range);
+ }
+ } catch (e) {}
+}
+
+//--------------------------------------------------------------------
+function initFontStyleMenu(menuPopup)
+{
+ for (var i = 0; i < menuPopup.childNodes.length; i++)
+ {
+ var menuItem = menuPopup.childNodes[i];
+ var theStyle = menuItem.getAttribute("state");
+ if (theStyle)
+ {
+ menuItem.setAttribute("checked", theStyle);
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+function onButtonUpdate(button, commmandID)
+{
+ var commandNode = document.getElementById(commmandID);
+ var state = commandNode.getAttribute("state");
+ button.checked = state == "true";
+}
+
+//--------------------------------------------------------------------
+function onStateButtonUpdate(button, commmandID, onState)
+{
+ var commandNode = document.getElementById(commmandID);
+ var state = commandNode.getAttribute("state");
+
+ button.checked = state == onState;
+}
+
+// --------------------------- Status calls ---------------------------
+function getColorAndSetColorWell(ColorPickerID, ColorWellID)
+{
+ var colorWell;
+ if (ColorWellID)
+ colorWell = document.getElementById(ColorWellID);
+
+ var colorPicker = document.getElementById(ColorPickerID);
+ if (colorPicker)
+ {
+ // Extract color from colorPicker and assign to colorWell.
+ var color = colorPicker.getAttribute("color");
+
+ if (colorWell && color)
+ {
+ // Use setAttribute so colorwell can be a XUL element, such as button
+ colorWell.setAttribute("style", "background-color: " + color);
+ }
+ }
+ return color;
+}
+
+//-----------------------------------------------------------------------------------
+function IsSpellCheckerInstalled()
+{
+ return "@mozilla.org/spellchecker;1" in Components.classes;
+}
+
+//-----------------------------------------------------------------------------------
+function IsFindInstalled()
+{
+ return "@mozilla.org/embedcomp/rangefind;1" in Components.classes
+ && "@mozilla.org/find/find_service;1" in Components.classes;
+}
+
+//-----------------------------------------------------------------------------------
+function RemoveInapplicableUIElements()
+{
+ // For items that are in their own menu block, remove associated separator
+ // (we can't use "hidden" since class="hide-in-IM" CSS rule interferes)
+
+ // if no find, remove find ui
+ if (!IsFindInstalled())
+ {
+ HideItem("menu_find");
+ HideItem("menu_findnext");
+ HideItem("menu_replace");
+ HideItem("menu_find");
+ RemoveItem("sep_find");
+ }
+
+ // if no spell checker, remove spell checker ui
+ if (!IsSpellCheckerInstalled())
+ {
+ HideItem("spellingButton");
+ HideItem("menu_checkspelling");
+ RemoveItem("sep_checkspelling");
+ }
+ else
+ {
+ SetElementEnabled(document.getElementById("menu_checkspelling"), true);
+ SetElementEnabled(document.getElementById("spellingButton"), true);
+ SetElementEnabled(document.getElementById("checkspellingkb"), true);
+ }
+
+ // Remove menu items (from overlay shared with HTML editor) in non-HTML.
+ if (!IsHTMLEditor())
+ {
+ HideItem("insertAnchor");
+ HideItem("insertImage");
+ HideItem("insertHline");
+ HideItem("insertTable");
+ HideItem("insertHTML");
+ HideItem("insertFormMenu");
+ HideItem("fileExportToText");
+ HideItem("viewFormatToolbar");
+ HideItem("viewEditModeToolbar");
+ }
+}
+
+function HideItem(id)
+{
+ var item = document.getElementById(id);
+ if (item)
+ item.hidden = true;
+}
+
+function RemoveItem(id)
+{
+ var item = document.getElementById(id);
+ if (item)
+ item.parentNode.removeChild(item);
+}
+
+// Command Updating Strategy:
+// Don't update on on selection change, only when menu is displayed,
+// with this "oncreate" hander:
+function EditorInitTableMenu()
+{
+ try {
+ InitJoinCellMenuitem("menu_JoinTableCells");
+ } catch (ex) {}
+
+ // Set enable states for all table commands
+ goUpdateTableMenuItems(document.getElementById("composerTableMenuItems"));
+}
+
+function InitJoinCellMenuitem(id)
+{
+ // Change text on the "Join..." item depending if we
+ // are joining selected cells or just cell to right
+ // TODO: What to do about normal selection that crosses
+ // table border? Try to figure out all cells
+ // included in the selection?
+ var menuText;
+ var menuItem = document.getElementById(id);
+ if (!menuItem) return;
+
+ // Use "Join selected cells if there's more than 1 cell selected
+ var numSelected;
+ var foundElement;
+
+ try {
+ var tagNameObj = {};
+ var countObj = {value:0}
+ foundElement = GetCurrentTableEditor().getSelectedOrParentTableElement(tagNameObj, countObj);
+ numSelected = countObj.value
+ }
+ catch(e) {}
+ if (foundElement && numSelected > 1)
+ menuText = GetString("JoinSelectedCells");
+ else
+ menuText = GetString("JoinCellToRight");
+
+ menuItem.setAttribute("label",menuText);
+ menuItem.setAttribute("accesskey",GetString("JoinCellAccesskey"));
+}
+
+function InitRemoveStylesMenuitems(removeStylesId, removeLinksId, removeNamedAnchorsId)
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ return;
+
+ // Change wording of menuitems depending on selection
+ var stylesItem = document.getElementById(removeStylesId);
+ var linkItem = document.getElementById(removeLinksId);
+
+ var isCollapsed = editor.selection.isCollapsed;
+ if (stylesItem)
+ {
+ stylesItem.setAttribute("label", isCollapsed ? GetString("StopTextStyles") : GetString("RemoveTextStyles"));
+ stylesItem.setAttribute("accesskey", GetString("RemoveTextStylesAccesskey"));
+ }
+ if (linkItem)
+ {
+ linkItem.setAttribute("label", isCollapsed ? GetString("StopLinks") : GetString("RemoveLinks"));
+ linkItem.setAttribute("accesskey", GetString("RemoveLinksAccesskey"));
+ // Note: disabling text style is a pain since there are so many - forget it!
+
+ // Disable if not in a link, but always allow "Remove"
+ // if selection isn't collapsed since we only look at anchor node
+ try {
+ SetElementEnabled(linkItem, !isCollapsed ||
+ editor.getElementOrParentByTagName("href", null));
+ } catch(e) {}
+ }
+ // Disable if selection is collapsed
+ SetElementEnabledById(removeNamedAnchorsId, !isCollapsed);
+}
+
+function goUpdateTableMenuItems(commandset)
+{
+ var editor = GetCurrentTableEditor();
+ if (!editor)
+ {
+ dump("goUpdateTableMenuItems: too early, not initialized\n");
+ return;
+ }
+
+ var enabled = false;
+ var enabledIfTable = false;
+
+ var flags = editor.flags;
+ if (!(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
+ IsEditingRenderedHTML())
+ {
+ var tagNameObj = { value: "" };
+ var element;
+ try {
+ element = editor.getSelectedOrParentTableElement(tagNameObj, {value:0});
+ }
+ catch(e) {}
+
+ if (element)
+ {
+ // Value when we need to have a selected table or inside a table
+ enabledIfTable = true;
+
+ // All others require being inside a cell or selected cell
+ enabled = (tagNameObj.value == "td");
+ }
+ }
+
+ // Loop through command nodes
+ for (var i = 0; i < commandset.childNodes.length; i++)
+ {
+ var commandID = commandset.childNodes[i].getAttribute("id");
+ if (commandID)
+ {
+ if (commandID == "cmd_InsertTable" ||
+ commandID == "cmd_JoinTableCells" ||
+ commandID == "cmd_SplitTableCell" ||
+ commandID == "cmd_ConvertToTable")
+ {
+ // Call the update method in the command class
+ goUpdateCommand(commandID);
+ }
+ // Directly set with the values calculated here
+ else if (commandID == "cmd_DeleteTable" ||
+ commandID == "cmd_NormalizeTable" ||
+ commandID == "cmd_editTable" ||
+ commandID == "cmd_TableOrCellColor" ||
+ commandID == "cmd_SelectTable")
+ {
+ goSetCommandEnabled(commandID, enabledIfTable);
+ } else {
+ goSetCommandEnabled(commandID, enabled);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+// Helpers for inserting and editing tables:
+
+function IsInTable()
+{
+ var editor = GetCurrentEditor();
+ try {
+ var flags = editor.flags;
+ return (IsHTMLEditor() &&
+ !(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
+ IsEditingRenderedHTML() &&
+ null != editor.getElementOrParentByTagName("table", null));
+ } catch (e) {}
+ return false;
+}
+
+function IsInTableCell()
+{
+ try {
+ var editor = GetCurrentEditor();
+ var flags = editor.flags;
+ return (IsHTMLEditor() &&
+ !(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
+ IsEditingRenderedHTML() &&
+ null != editor.getElementOrParentByTagName("td", null));
+ } catch (e) {}
+ return false;
+
+}
+
+function IsSelectionInOneCell()
+{
+ try {
+ var editor = GetCurrentEditor();
+ var selection = editor.selection;
+
+ if (selection.rangeCount == 1)
+ {
+ // We have a "normal" single-range selection
+ if (!selection.isCollapsed &&
+ selection.anchorNode != selection.focusNode)
+ {
+ // Check if both nodes are within the same cell
+ var anchorCell = editor.getElementOrParentByTagName("td", selection.anchorNode);
+ var focusCell = editor.getElementOrParentByTagName("td", selection.focusNode);
+ return (focusCell != null && anchorCell != null && (focusCell == anchorCell));
+ }
+ // Collapsed selection or anchor == focus (thus must be in 1 cell)
+ return true;
+ }
+ } catch (e) {}
+ return false;
+}
+
+// Call this with insertAllowed = true to allow inserting if not in existing table,
+// else use false to do nothing if not in a table
+function EditorInsertOrEditTable(insertAllowed)
+{
+ if (IsInTable())
+ {
+ // Edit properties of existing table
+ window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "","TablePanel");
+ gContentWindow.focus();
+ }
+ else if (insertAllowed)
+ {
+ try {
+ if (GetCurrentEditor().selection.isCollapsed)
+ // If we have a caret, insert a blank table...
+ EditorInsertTable();
+ else
+ // else convert the selection into a table
+ goDoCommand("cmd_ConvertToTable");
+ } catch (e) {}
+ }
+}
+
+function EditorInsertTable()
+{
+ // Insert a new table
+ window.openDialog("chrome://editor/content/EdInsertTable.xul", "_blank", "chrome,close,titlebar,modal", "");
+ gContentWindow.focus();
+}
+
+function EditorTableCellProperties()
+{
+ if (!IsHTMLEditor())
+ return;
+
+ try {
+ var cell = GetCurrentEditor().getElementOrParentByTagName("td", null);
+ if (cell) {
+ // Start Table Properties dialog on the "Cell" panel
+ window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "", "CellPanel");
+ gContentWindow.focus();
+ }
+ } catch (e) {}
+}
+
+function GetNumberOfContiguousSelectedRows()
+{
+ if (!IsHTMLEditor())
+ return 0;
+
+ var rows = 0;
+ try {
+ var editor = GetCurrentTableEditor();
+ var rowObj = { value: 0 };
+ var colObj = { value: 0 };
+ var cell = editor.getFirstSelectedCellInTable(rowObj, colObj);
+ if (!cell)
+ return 0;
+
+ // We have at least one row
+ rows++;
+
+ var lastIndex = rowObj.value;
+ do {
+ cell = editor.getNextSelectedCell({value:0});
+ if (cell)
+ {
+ editor.getCellIndexes(cell, rowObj, colObj);
+ var index = rowObj.value;
+ if (index == lastIndex + 1)
+ {
+ lastIndex = index;
+ rows++;
+ }
+ }
+ }
+ while (cell);
+ } catch (e) {}
+
+ return rows;
+}
+
+function GetNumberOfContiguousSelectedColumns()
+{
+ if (!IsHTMLEditor())
+ return 0;
+
+ var columns = 0;
+ try {
+ var editor = GetCurrentTableEditor();
+ var colObj = { value: 0 };
+ var rowObj = { value: 0 };
+ var cell = editor.getFirstSelectedCellInTable(rowObj, colObj);
+ if (!cell)
+ return 0;
+
+ // We have at least one column
+ columns++;
+
+ var lastIndex = colObj.value;
+ do {
+ cell = editor.getNextSelectedCell({value:0});
+ if (cell)
+ {
+ editor.getCellIndexes(cell, rowObj, colObj);
+ var index = colObj.value;
+ if (index == lastIndex +1)
+ {
+ lastIndex = index;
+ columns++;
+ }
+ }
+ }
+ while (cell);
+ } catch (e) {}
+
+ return columns;
+}
+
+function EditorOnFocus()
+{
+ // Current window already has the InsertCharWindow
+ if ("InsertCharWindow" in window && window.InsertCharWindow) return;
+
+ // Find window with an InsertCharsWindow and switch association to this one
+ var windowWithDialog = FindEditorWithInsertCharDialog();
+ if (windowWithDialog)
+ {
+ // Switch the dialog to current window
+ // this sets focus to dialog, so bring focus back to editor window
+ if (SwitchInsertCharToThisWindow(windowWithDialog))
+ top.document.commandDispatcher.focusedWindow.focus();
+ }
+}
+
+function SwitchInsertCharToThisWindow(windowWithDialog)
+{
+ if (windowWithDialog && "InsertCharWindow" in windowWithDialog &&
+ windowWithDialog.InsertCharWindow)
+ {
+ // Move dialog association to the current window
+ window.InsertCharWindow = windowWithDialog.InsertCharWindow;
+ windowWithDialog.InsertCharWindow = null;
+
+ // Switch the dialog's opener to current window's
+ window.InsertCharWindow.opener = window;
+
+ // Bring dialog to the forground
+ window.InsertCharWindow.focus();
+ return true;
+ }
+ return false;
+}
+
+function FindEditorWithInsertCharDialog()
+{
+ try {
+ // Find window with an InsertCharsWindow and switch association to this one
+ var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
+ var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
+ var enumerator = windowManagerInterface.getEnumerator( null );
+
+ while ( enumerator.hasMoreElements() )
+ {
+ var tempWindow = enumerator.getNext();
+
+ if (tempWindow != window && "InsertCharWindow" in tempWindow &&
+ tempWindow.InsertCharWindow)
+ {
+ return tempWindow;
+ }
+ }
+ }
+ catch(e) {}
+ return null;
+}
+
+function EditorFindOrCreateInsertCharWindow()
+{
+ if ("InsertCharWindow" in window && window.InsertCharWindow)
+ window.InsertCharWindow.focus();
+ else
+ {
+ // Since we switch the dialog during EditorOnFocus(),
+ // this should really never be found, but it's good to be sure
+ var windowWithDialog = FindEditorWithInsertCharDialog();
+ if (windowWithDialog)
+ {
+ SwitchInsertCharToThisWindow(windowWithDialog);
+ }
+ else
+ {
+ // The dialog will set window.InsertCharWindow to itself
+ window.openDialog("chrome://editor/content/EdInsertChars.xul", "_blank", "chrome,close,titlebar", "");
+ }
+ }
+}
+
+// Find another HTML editor window to associate with the InsertChar dialog
+// or close it if none found (May be a mail composer)
+function SwitchInsertCharToAnotherEditorOrClose()
+{
+ if ("InsertCharWindow" in window && window.InsertCharWindow)
+ {
+ var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
+ var enumerator;
+ try {
+ var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
+ enumerator = windowManagerInterface.getEnumerator( null );
+ }
+ catch(e) {}
+ if (!enumerator) return;
+
+ // TODO: Fix this to search for command controllers and look for "cmd_InsertChars"
+ // For now, detect just Web Composer and HTML Mail Composer
+ while ( enumerator.hasMoreElements() )
+ {
+ var tempWindow = enumerator.getNext();
+ if (tempWindow != window && tempWindow != window.InsertCharWindow &&
+ "GetCurrentEditor" in tempWindow && tmpWindow.GetCurrentEditor())
+ {
+ tempWindow.InsertCharWindow = window.InsertCharWindow;
+ window.InsertCharWindow = null;
+ tempWindow.InsertCharWindow.opener = tempWindow;
+ return;
+ }
+ }
+ // Didn't find another editor - close the dialog
+ window.InsertCharWindow.close();
+ }
+}
+
+function ResetStructToolbar()
+{
+ gLastFocusNode = null;
+ UpdateStructToolbar();
+}
+
+function newCommandListener(element)
+{
+ return function() { return SelectFocusNodeAncestor(element); };
+}
+
+function newContextmenuListener(button, element)
+{
+ return function() { return InitStructBarContextMenu(button, element); };
+}
+
+function UpdateStructToolbar()
+{
+ var editor = GetCurrentEditor();
+ if (!editor) return;
+
+ var mixed = GetSelectionContainer();
+ if (!mixed) return;
+ var element = mixed.node;
+ var oneElementSelected = mixed.oneElementSelected;
+
+ if (!element) return;
+
+ if (element == gLastFocusNode &&
+ oneElementSelected == gLastFocusNodeWasSelected)
+ return;
+
+ gLastFocusNode = element;
+ gLastFocusNodeWasSelected = mixed.oneElementSelected;
+
+ var toolbar = document.getElementById("structToolbar");
+ if (!toolbar) return;
+ var childNodes = toolbar.childNodes;
+ var childNodesLength = childNodes.length;
+ // We need to leave the <label> to flex the buttons to the left
+ // so, don't remove the last child at position length - 1
+ while (childNodes.length > 1) {
+ // Remove back to front so there's less moving about.
+ toolbar.removeChild(childNodes.item(childNodes.length - 2));
+ }
+
+ toolbar.removeAttribute("label");
+
+ if ( IsInHTMLSourceMode() ) {
+ // we have destroyed the contents of the status bar and are
+ // about to recreate it ; but we don't want to do that in
+ // Source mode
+ return;
+ }
+
+ var tag, button;
+ var bodyElement = GetBodyElement();
+ var isFocusNode = true;
+ var tmp;
+ do {
+ tag = element.nodeName.toLowerCase();
+
+ button = document.createElementNS(XUL_NS, "toolbarbutton");
+ button.setAttribute("label", "<" + tag + ">");
+ button.setAttribute("value", tag);
+ button.setAttribute("context", "structToolbarContext");
+ button.className = "struct-button";
+
+ toolbar.insertBefore(button, toolbar.firstChild);
+
+ button.addEventListener("command", newCommandListener(element), false);
+
+ button.addEventListener("contextmenu", newContextmenuListener(button, element), false);
+
+ if (isFocusNode && oneElementSelected) {
+ button.setAttribute("checked", "true");
+ isFocusNode = false;
+ }
+
+ tmp = element;
+ element = element.parentNode;
+
+ } while (tmp != bodyElement);
+}
+
+function SelectFocusNodeAncestor(element)
+{
+ var editor = GetCurrentEditor();
+ if (editor) {
+ if (element == GetBodyElement())
+ editor.selectAll();
+ else
+ editor.selectElement(element);
+ }
+ ResetStructToolbar();
+}
+
+function GetSelectionContainer()
+{
+ var editor = GetCurrentEditor();
+ if (!editor) return null;
+
+ try {
+ var selection = editor.selection;
+ if (!selection) return null;
+ }
+ catch (e) { return null; }
+
+ var result = { oneElementSelected:false };
+
+ if (selection.isCollapsed) {
+ result.node = selection.focusNode;
+ }
+ else {
+ var rangeCount = selection.rangeCount;
+ if (rangeCount == 1) {
+ result.node = editor.getSelectedElement("");
+ var range = selection.getRangeAt(0);
+
+ // check for a weird case : when we select a piece of text inside
+ // a text node and apply an inline style to it, the selection starts
+ // at the end of the text node preceding the style and ends after the
+ // last char of the style. Assume the style element is selected for
+ // user's pleasure
+ if (!result.node &&
+ range.startContainer.nodeType == Node.TEXT_NODE &&
+ range.startOffset == range.startContainer.length &&
+ range.endContainer.nodeType == Node.TEXT_NODE &&
+ range.endOffset == range.endContainer.length &&
+ range.endContainer.nextSibling == null &&
+ range.startContainer.nextSibling == range.endContainer.parentNode)
+ result.node = range.endContainer.parentNode;
+
+ if (!result.node) {
+ // let's rely on the common ancestor of the selection
+ result.node = range.commonAncestorContainer;
+ }
+ else {
+ result.oneElementSelected = true;
+ }
+ }
+ else {
+ // assume table cells !
+ var i, container = null;
+ for (i = 0; i < rangeCount; i++) {
+ range = selection.getRangeAt(i);
+ if (!container) {
+ container = range.startContainer;
+ }
+ else if (container != range.startContainer) {
+ // all table cells don't belong to same row so let's
+ // select the parent of all rows
+ result.node = container.parentNode;
+ break;
+ }
+ result.node = container;
+ }
+ }
+ }
+
+ // make sure we have an element here
+ while (result.node.nodeType != Node.ELEMENT_NODE)
+ result.node = result.node.parentNode;
+
+ // and make sure the element is not a special editor node like
+ // the <br> we insert in blank lines
+ // and don't select anonymous content !!! (fix for bug 190279)
+ while (result.node.hasAttribute("_moz_editor_bogus_node") ||
+ editor.isAnonymousElement(result.node))
+ result.node = result.node.parentNode;
+
+ return result;
+}
+
+function FillInHTMLTooltipEditor(tooltip)
+{
+ const XLinkNS = "http://www.w3.org/1999/xlink";
+ var tooltipText = null;
+ var node;
+ if (gEditorDisplayMode == kDisplayModePreview) {
+ for (node = document.tooltipNode; node; node = node.parentNode) {
+ if (node.nodeType == Node.ELEMENT_NODE) {
+ tooltipText = node.getAttributeNS(XLinkNS, "title");
+ if (tooltipText && /\S/.test(tooltipText)) {
+ tooltip.setAttribute("label", tooltipText);
+ return true;
+ }
+ tooltipText = node.getAttribute("title");
+ if (tooltipText && /\S/.test(tooltipText)) {
+ tooltip.setAttribute("label", tooltipText);
+ return true;
+ }
+ }
+ }
+ } else {
+ for (node = document.tooltipNode; node; node = node.parentNode) {
+ if (node instanceof Components.interfaces.nsIDOMHTMLImageElement ||
+ node instanceof Components.interfaces.nsIDOMHTMLInputElement)
+ tooltipText = node.getAttribute("src");
+ else if (node instanceof Components.interfaces.nsIDOMHTMLAnchorElement)
+ tooltipText = node.getAttribute("href") || node.name;
+ if (tooltipText) {
+ tooltip.setAttribute("label", tooltipText);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+function UpdateTOC()
+{
+ window.openDialog("chrome://editor/content/EdInsertTOC.xul",
+ "_blank", "chrome,close,modal,titlebar");
+ window.content.focus();
+}
+
+function InitTOCMenu()
+{
+ var elt = GetCurrentEditor().document.getElementById("mozToc");
+ var createMenuitem = document.getElementById("insertTOCMenuitem");
+ var updateMenuitem = document.getElementById("updateTOCMenuitem");
+ var removeMenuitem = document.getElementById("removeTOCMenuitem");
+ if (removeMenuitem && createMenuitem && updateMenuitem) {
+ if (elt) {
+ createMenuitem.setAttribute("disabled", "true");
+ updateMenuitem.removeAttribute("disabled");
+ removeMenuitem.removeAttribute("disabled");
+ }
+ else {
+ createMenuitem.removeAttribute("disabled");
+ removeMenuitem.setAttribute("disabled", "true");
+ updateMenuitem.setAttribute("disabled", "true");
+ }
+ }
+}
+
+function RemoveTOC()
+{
+ var theDocument = GetCurrentEditor().document;
+ var elt = theDocument.getElementById("mozToc");
+ if (elt) {
+ elt.parentNode.removeChild(elt);
+ }
+
+ function acceptNode(node)
+ {
+ if (node.nodeName.toLowerCase() == "a" &&
+ node.hasAttribute("name") &&
+ node.getAttribute("name").substr(0, 8) == "mozTocId") {
+ return NodeFilter.FILTER_ACCEPT;
+ }
+ return NodeFilter.FILTER_SKIP;
+ }
+
+ var treeWalker = theDocument.createTreeWalker(theDocument.documentElement,
+ NodeFilter.SHOW_ELEMENT,
+ acceptNode,
+ true);
+ if (treeWalker) {
+ var anchorNode = treeWalker.nextNode();
+ while (anchorNode) {
+ var tmp = treeWalker.nextNode();
+ anchorNode.parentNode.removeChild(anchorNode);
+ anchorNode = tmp;
+ }
+ }
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editor.xul
@@ -0,0 +1,311 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Ben Goodger
+ - Michael Lowe
+ - Sammy Ford
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
+
+<?xml-stylesheet href="chrome://editor/skin/editorPrimaryToolbar.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/editorFormatToolbar.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/editorModeToolbar.css" type="text/css"?>
+<?xul-overlay href="chrome://editor/content/editorOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/composerOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EditorContextMenuOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/charsetOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/tasksOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/contentAreaContextOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/sidebar/sidebarOverlay.xul"?>
+
+<!DOCTYPE window [
+<!ENTITY % editorDTD SYSTEM "chrome://editor/locale/editor.dtd" >
+%editorDTD;
+<!ENTITY % editorOverlayDTD SYSTEM "chrome://editor/locale/editorOverlay.dtd" >
+%editorOverlayDTD;
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+%brandDTD;
+]>
+
+<window id="editorWindow"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="EditorOnLoad()"
+ onunload="EditorShutdown()"
+ onclose="return EditorCanClose()"
+ onfocus="EditorOnFocus()"
+ contenttitlesetting="true"
+ titlemodifier="&editorWindow.titlemodifier;"
+ titlemenuseparator="&editorWindow.titlemodifiermenuseparator;"
+ windowtype="composer:html"
+ width="640" height="480"
+ screenX="10" screenY="10"
+ persist="screenX screenY width height sizemode">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editor.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditorContextMenu.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/StructBarContextMenu.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/editorApplicationOverlay.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/publishprefs.js"/>
+ <script type="application/x-javascript" src="chrome://communicator/content/contentAreaDD.js"/>
+ <script type="application/x-javascript" src="chrome://communicator/content/contentAreaClick.js"/>
+ <script type="application/x-javascript" src="chrome://global/content/printUtils.js"/>
+ <script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
+
+ <popupset id="editorContentContextSet"/>
+ <popup id="sidebarPopup"/>
+ <popup id="popupNotificationMenu"/>
+
+ <commandset id="tasksCommands">
+ <commandset id="globalEditMenuItems"/>
+ <commandset id="selectEditMenuItems"/>
+ <commandset id="undoEditMenuItems"/>
+ <commandset id="clipboardEditMenuItems"/>
+
+ <commandset id="commonEditorMenuItems"/>
+ <commandset id="composerMenuItems"/>
+ <commandset id="composerEditMenuItems"/>
+ <commandset id="composerSaveMenuItems"/>
+ <commandset id="composerStyleMenuItems"/>
+ <commandset id="composerTableMenuItems"/>
+ <commandset id="composerListMenuItems"/>
+ <command id="toggleSidebar"/>
+ </commandset>
+
+ <tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltipEditor(this);"/>
+
+ <broadcaster id="args" value="about:blank"/>
+ <broadcaster id="canPrint"/>
+
+ <!-- Interim hack to transition from nsIXULWindowCallbacks/ShowWindowWithArgs
+ <broadcaster id="dialog.start" ready="false"/>
+ <observes element="dialog.start" attribute="ready" onbroadcast="EditorStartup('html')"/>
+-->
+ <broadcasterset id="broadcasterset">
+ <broadcaster id="Editor:Throbber" busy="false"/>
+ <broadcaster id="Communicator:WorkMode"/>
+ </broadcasterset>
+
+ <!-- keys are appended from the overlay -->
+ <keyset id="editorKeys">
+ <keyset id="tasksKeys"/>
+ <key id="showHideSidebar"/>
+ <!-- eat these tab events here to stop focus from moving -->
+ <key keycode="VK_TAB" oncommand="return true;"/>
+ <key keycode="VK_TAB" modifiers="shift" oncommand="return true;"/>
+ <key keycode="VK_TAB" modifiers="control" oncommand="return true;"/>
+ <key keycode="VK_TAB" modifiers="control,shift" oncommand="return true;"/>
+ </keyset>
+
+ <toolbox class="toolbox-top" id="EditorToolbox">
+ <menubar id="main-menubar" class="chromeclass-menubar" persist="collapsed" grippytooltiptext="&menuBar.tooltip;">
+ <menu id="fileMenu"/>
+ <menu id="editMenu"/>
+
+ <menu id="viewMenu" label="&viewMenu.label;" accesskey="&viewmenu.accesskey;">
+ <!-- id pulls in "Show Sidebar" item from sidebarOverlay -->
+ <menupopup id="menu_View_Popup">
+ <menu id="menu_Toolbars">
+ <menupopup id="view_toolbars_popup">
+ <menuitem id="viewComposerToolbar" label="&compositionToolbarCmd.label;" type="checkbox" accesskey="&compositiontb.accesskey;" command="cmd_viewCompToolbar" />
+ <menuitem id="viewFormatToolbar" label="&formattingToolbarCmd.label;" type="checkbox" accesskey="&formattingtb.accesskey;" command="cmd_viewFormatToolbar" />
+ <menuitem id="viewEditModeToolbar" label="&editmodeToolbarCmd.label;" type="checkbox" accesskey="&editmodetb.accesskey;" command="cmd_viewEditModeToolbar" />
+ <menuitem id="menu_showTaskbar"/>
+ </menupopup>
+ </menu>
+ <menuseparator id="viewSep1"/>
+ <menuitem id="viewNormalMode" checked="true"/>
+ <menuitem id="viewAllTagsMode"/>
+ <menuitem id="viewSourceMode"/>
+ <menuitem id="viewPreviewMode"/>
+ <menuseparator id="viewSep2"/>
+ <menu id = "composerCharsetMenu" />
+ </menupopup>
+ </menu>
+
+ <menu id="insertMenu"/>
+
+ <menu id="formatMenu" label="&formatMenu.label;" accesskey="&formatmenu.accesskey;">
+ <menupopup id="formatMenuPopup">
+ <menuitem id="snapToGrid"/>
+ <menuseparator/>
+ <menuitem id="objectProperties"/>
+ <menuitem id="colorsAndBackground"/>
+ <menuitem id="pageProperties"/>
+ </menupopup>
+ </menu>
+
+ <menu id="tableMenu"/>
+
+ <!-- tasks menu filled from tasksOverlay -->
+ <menu id="tasksMenu">
+ <menupopup id="taskPopup">
+ <menuitem id="menu_validate" observes="cmd_validate"/>
+ <menuseparator id="sep_validate"/>
+ </menupopup>
+ </menu>
+
+ <menu id="windowMenu"/>
+
+ <!-- help menu filled from globalOverlay -->
+ <menu id="menu_Help"/>
+
+ <spacer flex="1"/>
+ </menubar>
+
+ <!-- toolbar filled out from editorOverlay -->
+ <!-- add class="standard" for dark blue background (icons need rework first) -->
+ <toolbar class="chromeclass-toolbar toolbar-primary" id="EditToolbar" persist="collapsed"
+ grippytooltiptext="&compositionToolbar.tooltip;">
+ <toolbarbutton id="newButton"/>
+ <toolbarbutton id="openButton"/>
+ <toolbarbutton id="saveButton"/>
+ <toolbarbutton id="publishButton"/>
+ <toolbarbutton id="previewButton"/>
+ <toolbarbutton id="cutButton"/>
+ <toolbarbutton id="copyButton"/>
+ <toolbarbutton id="pasteButton"/>
+ <toolbarbutton id="printButton"/>
+ <toolbarbutton id="findButton"/>
+ <toolbarseparator class="toolbarseparator-primary"/>
+ <toolbarbutton id="linkButton"/>
+ <toolbarbutton id="namedAnchorButton"/>
+ <toolbarbutton id="imageButton"/>
+ <toolbarbutton id="hlineButton"/>
+ <toolbarbutton id="tableButton"/>
+ <toolbarbutton id="spellingButton"/>
+ <spacer flex="1"/>
+ <hbox id="throbber-box" align="center">
+ <button id="navigator-throbber" oncommand="goClickThrobber('editor.throbber.url')" tooltiptext="&throbber.tooltip;">
+ <observes element="Editor:Throbber" attribute="busy"/>
+ </button>
+ </hbox>
+ </toolbar>
+ <toolbar class="chromeclass-toolbar" id="FormatToolbar" persist="collapsed" grippytooltiptext="&formatToolbar.tooltip;">
+ <!-- from editorOverlay -->
+ <menulist id="ParagraphSelect"/>
+ <stack id="ColorButtons"/>
+ <toolbarbutton id="HighlightColorButton"/>
+
+ <toolbarseparator class="toolbarseparator-standard"/>
+
+ <toolbarbutton id="DecreaseFontSizeButton"/>
+ <toolbarbutton id="IncreaseFontSizeButton"/>
+
+ <toolbarseparator class="toolbarseparator-standard"/>
+
+ <toolbarbutton id="boldButton"/>
+ <toolbarbutton id="italicButton"/>
+ <toolbarbutton id="underlineButton"/>
+
+ <toolbarseparator class="toolbarseparator-standard"/>
+
+ <toolbarbutton id="ulButton"/>
+ <toolbarbutton id="olButton"/>
+ <toolbarbutton id="outdentButton"/>
+ <toolbarbutton id="indentButton"/>
+
+ <toolbarseparator class="toolbarseparator-standard"/>
+
+ <toolbarbutton id="align-left-button"/>
+ <toolbarbutton id="align-center-button"/>
+ <toolbarbutton id="align-right-button"/>
+ <toolbarbutton id="align-justify-button"/>
+
+ <toolbarbutton id="absolutePositionButton"/>
+ <toolbarbutton id="decreaseZIndexButton"/>
+ <toolbarbutton id="increaseZIndexButton"/>
+
+ <!-- TODO: Change to a menulist? -->
+ <!-- menu>
+ <button id="AlignPopupButton"/>
+ <menupopup id="AlignmentPopup"/>
+ </menu -->
+
+
+ <spacer flex="1"/>
+ </toolbar>
+</toolbox>
+
+<!-- sidebar/toolbar/content/status -->
+<hbox id="sidebar-parent" flex="1">
+ <!-- From sidebarOverlay.xul -->
+ <vbox id="sidebar-box" class="chromeclass-extrachrome" hidden="true"/>
+ <splitter id="sidebar-splitter" class="chromeclass-extrachrome" hidden="true"/>
+
+ <vbox id="appcontent" flex="1">
+ <deck id="ContentWindowDeck" selectedIndex="0" flex="1">
+ <!-- KLUDGE: Temporary fix for bug 34414:
+ The current editor tag doesn't have a view,
+ which breaks deck frame-hiding mechanism
+ -->
+ <stack>
+ <editor editortype="html" type="content-primary" id="content-frame"
+ context="editorContentContext" flex="1" tooltip="aHTMLTooltip"/>
+ </stack>
+ <vbox>
+ <label id="doctype-text" crop="right"/>
+ <editor type="content" id="content-source" context="editorSourceContext" flex="1"/>
+ </vbox>
+ </deck>
+
+ <hbox id="EditModeToolbar" align="center" hidden="false" persist="collapsed">
+ <tabs id="EditModeTabs" class="tabs-bottom" flex="1">
+ <tab id="NormalModeButton"/>
+ <tab id="TagModeButton"/>
+ <tab id="SourceModeButton"/>
+ <tab id="PreviewModeButton"/>
+ </tabs>
+ </hbox>
+
+ </vbox> <!-- appcontent -->
+</hbox><!-- sidebar-parent -->
+
+ <!-- Some of this is from globarOverlay.xul -->
+ <statusbar class="chromeclass-status" id="status-bar">
+ <statusbarpanel id="component-bar"/>
+ <statusbarpanel id="structToolbar" flex="1" pack="end">
+ <label id="structSpacer" value="" flex="1"/>
+ </statusbarpanel>
+ <statusbarpanel class="statusbarpanel-iconic" id="offline-status"/>
+ </statusbar>
+
+
+
+</window>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorApplicationOverlay.js
@@ -0,0 +1,169 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementations of nsIControllerCommand for composer commands */
+
+function initEditorContextMenuItems(aEvent)
+{
+ var shouldShowEditPage = !gContextMenu.onImage && !gContextMenu.onLink && !gContextMenu.onTextInput && !gContextMenu.inDirList;
+ gContextMenu.showItem( "context-editpage", shouldShowEditPage );
+
+ var shouldShowEditLink = gContextMenu.onSaveableLink;
+ gContextMenu.showItem( "context-editlink", shouldShowEditLink );
+
+ // Hide the applications separator if there's no add-on apps present.
+ gContextMenu.showItem("context-sep-apps", gContextMenu.shouldShowSeparator("context-sep-apps"));
+}
+
+function initEditorContextMenuListener(aEvent)
+{
+ var popup = document.getElementById("contentAreaContextMenu");
+ if (popup)
+ popup.addEventListener("popupshowing", initEditorContextMenuItems, false);
+}
+
+addEventListener("load", initEditorContextMenuListener, false);
+
+function editDocument(aDocument)
+{
+ if (!aDocument)
+ aDocument = window.content.document;
+
+ editPage(aDocument.URL);
+}
+
+function editPageOrFrame()
+{
+ var focusedWindow = document.commandDispatcher.focusedWindow;
+
+ // if the uri is a specific frame, grab it, else use the frameset uri
+ // and let Composer handle error if necessary
+ editPage(getContentFrameURI(focusedWindow));
+}
+
+// Any non-editor window wanting to create an editor with a URL
+// should use this instead of "window.openDialog..."
+// We must always find an existing window with requested URL
+function editPage(url)
+{
+ // Always strip off "view-source:" and #anchors
+ url = url.replace(/^view-source:/, "").replace(/#.*/, "");
+
+ // if the current window is a browser window, then extract the current charset menu setting from the current
+ // document and use it to initialize the new composer window...
+
+ var wintype = document.documentElement.getAttribute('windowtype');
+ var charsetArg;
+
+ if (wintype == "navigator:browser" && content.document)
+ charsetArg = "charset=" + content.document.characterSet;
+
+ try {
+ var uri = createURI(url, null, null);
+
+ var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
+ var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
+ var enumerator = windowManagerInterface.getEnumerator( "composer:html" );
+ var emptyWindow;
+ while ( enumerator.hasMoreElements() )
+ {
+ var win = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindowInternal);
+ if ( win && win.IsWebComposer())
+ {
+ if (CheckOpenWindowForURIMatch(uri, win))
+ {
+ // We found an editor with our url
+ win.focus();
+ return;
+ }
+ else if (!emptyWindow && win.PageIsEmptyAndUntouched())
+ {
+ emptyWindow = win;
+ }
+ }
+ }
+
+ if (emptyWindow)
+ {
+ // we have an empty window we can use
+ if (emptyWindow.IsInHTMLSourceMode())
+ emptyWindow.SetEditMode(emptyWindow.PreviousNonSourceDisplayMode);
+ emptyWindow.EditorLoadUrl(url);
+ emptyWindow.focus();
+ emptyWindow.SetSaveAndPublishUI(url);
+ return;
+ }
+
+ // Create new Composer window
+ openDialog("chrome://editor/content", "_blank", "chrome,all,dialog=no", url, charsetArg);
+
+ } catch(e) {}
+}
+
+function createURI(urlstring)
+{
+ try {
+ var ioserv = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ return ioserv.newURI(urlstring, null, null);
+ } catch (e) {}
+
+ return null;
+}
+
+function CheckOpenWindowForURIMatch(uri, win)
+{
+ try {
+ var contentWindow = win.content; // need to QI win to nsIDOMWindowInternal?
+ var contentDoc = contentWindow.document;
+ var htmlDoc = contentDoc.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
+ var winuri = createURI(htmlDoc.URL);
+ return winuri.equals(uri);
+ } catch (e) {}
+
+ return false;
+}
+
+function NewEditorFromTemplate()
+{
+ // XXX not implemented
+}
+
+function NewEditorFromDraft()
+{
+ // XXX not implemented
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorMailOverlay.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!-- retrieve generic commands -->
+<?xul-overlay href="chrome://messenger/content/mailOverlay.xul"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/editorNavigatorOverlay.dtd" >
+
+<overlay id="editorMailOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="editorApplicationOverlay.js"/>
+
+ <!-- navigator specific commands -->
+ <commandset id="tasksCommands">
+ <!-- XXX insert commands here -->
+ </commandset>
+
+ <!-- navigator specific UI items -->
+ <menupopup id="menu_NewPopup">
+ <!-- XXX insert File->New Menu add-ins here -->
+ </menupopup>
+
+ <menupopup id="menu_FilePopup">
+ <!-- XXX insert File Menu add-ins here -->
+ </menupopup>
+</overlay>
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorNavigatorOverlay.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!-- retrieve generic commands -->
+<!-- <?xul-overlay href="chrome://messenger/content/mailOverlay.xul"?> -->
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/editorNavigatorOverlay.dtd" >
+
+<overlay id="editorNavigatorOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="editorApplicationOverlay.js"/>
+
+ <!-- navigator specific commands -->
+ <commandset id="tasksCommands">
+ <!-- XXX insert commands here -->
+ </commandset>
+
+ <!-- navigator specific UI items -->
+ <menupopup id="menu_NewPopup">
+ <!-- XXX insert File->New Menu add-ins here -->
+ </menupopup>
+
+ <menupopup id="menu_FilePopup">
+ <!-- XXX insert File Menu add-ins here -->
+ </menupopup>
+</overlay>
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorOverlay.js
@@ -0,0 +1,51 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function EditorNew()
+{
+ dump("In EditorNew..\n");
+}
+
+function EditorNewFromTemplate()
+{
+ dump("In EditorNewFromTemplate..\n");
+}
+
+function EditorNewFromDraft()
+{
+ dump("In EditorNewFromDraft..\n");
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorOverlay.xul
@@ -0,0 +1,918 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Ryan Cassin (rcassin@supernova.org)
+ - Daniel Glazman (glazman@netscape.com)
+ - Aaron Kaluszka (ask@swva.net)
+ - Stephen Donner (technutz@netscape.net)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay [
+<!ENTITY % editorOverlayDTD SYSTEM "chrome://editor/locale/editorOverlay.dtd">
+%editorOverlayDTD;
+<!ENTITY % platformCommunicatorDTD SYSTEM
+ "chrome://communicator-platform/locale/platformCommunicatorOverlay.dtd">
+%platformCommunicatorDTD;
+]>
+
+<overlay id="editorOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+<script type="application/x-javascript" src="chrome://editor/content/ComposerCommands.js"/>
+
+ <keyset id="editorKeys">
+ <!-- defined in globalOverlay -->
+ <key id="key_newNavigator"/>
+ <key id="key_newBlankPage"/>
+
+ <key id="openeditorkb" key="&fileopen.keybinding;" observes="cmd_open" modifiers="accel"/>
+ <key id="openremoteeditorkb" key="&fileopenremote.keybinding;" observes="cmd_openRemote" modifiers="accel,shift"/>
+ <key id="savekb" key="&filesave.keybinding;" observes="cmd_save" modifiers="accel"/>
+ <key id="publishkb" key="&filesave.keybinding;" observes="cmd_publish" modifiers="accel,shift"/>
+ <key id="closekb" key="&fileclose.keybinding;" observes="cmd_close" modifiers="accel"/>
+ <key id="printkb" key="&fileprint.keybinding;" observes="cmd_print" modifiers="accel"/>
+ <key id="key_quit"/>
+ <key id="key_undo"/>
+ <key id="key_redo"/>
+ <key id="key_cut"/>
+ <key id="key_copy"/>
+ <key id="key_paste"/>
+ <key id="key_delete"/>
+ <key id="key_selectAll"/>
+ <key id="pastequotationkb" key="&editpastequotation.keybinding;" observes="cmd_pasteQuote" modifiers="accel, shift"/>
+ <key id="findkb" key="&editfind.keybinding;" observes="cmd_find" modifiers="accel"/>
+ <key id="findnextkb" key="&editfindnext.keybinding;" observes="cmd_findNext" modifiers="accel"/>
+ <key id="findprevkb" key="&editfindprev.keybinding;" observes="cmd_findPrev" modifiers="accel,shift"/>
+ <key keycode="&editfindnext.keybinding2;" observes="cmd_findNext"/>
+ <key keycode="&editfindprev.keybinding2;" observes="cmd_findPrev" modifiers="shift"/>
+#ifdef MOZ_X11
+ <key keycode="&editfind.keybinding2;" observes="cmd_find"/>
+#endif
+ <key id="checkspellingkb"
+ key="&editcheckspelling.keybinding;"
+ observes="cmd_spelling"
+ modifiers="&accel.emacs_conflict;"
+ disabled="true"
+ />
+
+ <key id="boldkb" key="&stylebold.keybinding;" observes="cmd_bold" modifiers="accel"/>
+ <key id="italickb" key="&styleitalic.keybinding;" observes="cmd_italic" modifiers="accel"/>
+ <key id="underlinekb" key="&styleunderline.keybinding;" observes="cmd_underline" modifiers="accel"/>
+ <key id="fixedwidthkb" key="&formatfontfixed.keybinding;" observes="cmd_tt" modifiers="accel"/>
+
+ <key id="increaseindentkb" key="&formatindent.keybinding;" observes="cmd_indent" modifiers="accel"/>
+ <key id="decreaseindentkb" key="&formatoutdent.keybinding;" observes="cmd_outdent" modifiers="accel"/>
+
+ <key id="removestyleskb" key="&formatremovestyles.keybinding;" observes="cmd_removeStyles" modifiers="accel, shift"/>
+ <key id="removestyleskb2" key=" " observes="cmd_removeStyles" modifiers="accel"/>
+ <key id="removelinkskb" key="&formatremovelinks.keybinding;" observes="cmd_removeLinks" modifiers="accel, shift"/>
+ <key id="removenamedanchorskb" key="&formatremovenamedanchors.keybinding;" observes="cmd_removeNamedAnchors" modifiers="accel, shift"/>
+ <key id="decreasefontsizekb" key="&decreaseFontSize.keybinding;" observes="cmd_decreaseFont" modifiers="accel"/>
+ <key id="increasefontsizekb" key="&increaseFontSize.keybinding;" observes="cmd_increaseFont" modifiers="accel"/>
+ <key key="&increaseFontSize.keybinding;" observes="cmd_increaseFont" modifiers="accel,shift"/>
+ <key key="&increaseFontSize.keybinding2;" observes="cmd_increaseFont" modifiers="accel"/>
+
+ <key id="insertlinkkb" key="&insertlink.keybinding;" observes="cmd_link" modifiers="accel"/>
+ </keyset>
+
+ <!-- commands updated when the editor gets created -->
+ <commandset id="commonEditorMenuItems"
+ commandupdater="true"
+ events="create"
+ oncommandupdate="goUpdateComposerMenuItems(this)"
+ >
+ <command id="cmd_open" oncommand="goDoCommand('cmd_open')"/>
+ <command id="cmd_openRemote" label="&openremoteCmd.label;" oncommand="goDoCommand('cmd_openRemote')"/>
+ <command id="cmd_close" label="&closeCmd.label;" oncommand="goDoCommand('cmd_close')"/>
+ <command id="cmd_printSetup" oncommand="goDoCommand('cmd_printSetup')"/>
+<!--
+ <command id="cmd_printPreview" label="&printPreviewCmd.label;" oncommand="goDoCommand('cmd_printPreview')"/>
+-->
+ <command id="cmd_print" oncommand="goDoCommand('cmd_print')"/>
+ <command id="cmd_quit" oncommand="goDoCommand('cmd_quit')"/>
+ </commandset>
+
+ <commandset id="composerMenuItems"
+ commandupdater="true"
+ events="create, mode_switch"
+ oncommandupdate="goUpdateComposerMenuItems(this)"
+ >
+ <!-- format menu -->
+ <command id="cmd_listProperties" oncommand="goDoCommand('cmd_listProperties')"/>
+ <command id="cmd_pageProperties" oncommand="goDoCommand('cmd_pageProperties')"/>
+ <command id="cmd_colorProperties" oncommand="goDoCommand('cmd_colorProperties')"/>
+
+ <command id="cmd_link" oncommand="goDoCommand('cmd_link')"/>
+ <command id="cmd_anchor" oncommand="goDoCommand('cmd_anchor')"/>
+ <command id="cmd_image" oncommand="goDoCommand('cmd_image')"/>
+ <command id="cmd_hline" oncommand="goDoCommand('cmd_hline')"/>
+ <command id="cmd_table" oncommand="goDoCommand('cmd_table')"/>
+ <command id="cmd_form" oncommand="goDoCommand('cmd_form')"/>
+ <command id="cmd_inputtag" oncommand="goDoCommand('cmd_inputtag')"/>
+ <command id="cmd_inputimage" oncommand="goDoCommand('cmd_inputimage')"/>
+ <command id="cmd_textarea" oncommand="goDoCommand('cmd_textarea')"/>
+ <command id="cmd_select" oncommand="goDoCommand('cmd_select')"/>
+ <command id="cmd_button" oncommand="goDoCommand('cmd_button')"/>
+ <command id="cmd_label" oncommand="goDoCommand('cmd_label')"/>
+ <command id="cmd_fieldset" oncommand="goDoCommand('cmd_fieldset')"/>
+ <command id="cmd_isindex" oncommand="goDoCommand('cmd_isindex')"/>
+ <command id="cmd_objectProperties" oncommand="goDoCommand('cmd_objectProperties')"/>
+ <command id="cmd_insertChars" oncommand="goDoCommand('cmd_insertChars')" label="&insertCharsCmd.label;"/>
+ <command id="cmd_insertHTMLWithDialog" oncommand="goDoCommand('cmd_insertHTMLWithDialog')" label="&insertHTMLCmd.label;"/>
+
+ <command id="cmd_insertBreak" oncommand="goDoCommand('cmd_insertBreak')"/>
+ <command id="cmd_insertBreakAll" oncommand="goDoCommand('cmd_insertBreakAll')"/>
+ <command id="cmd_NormalMode" oncommand="goDoCommand('cmd_NormalMode')" label="&NormalMode.label;"/>
+ <command id="cmd_AllTagsMode" oncommand="goDoCommand('cmd_AllTagsMode')" label="&AllTagsMode.label;"/>
+ <command id="cmd_HTMLSourceMode" oncommand="goDoCommand('cmd_HTMLSourceMode')"/>
+ <command id="cmd_PreviewMode" oncommand="goDoCommand('cmd_PreviewMode')" label="&PreviewMode.label;"/>
+
+ <!-- only used in context popup menu -->
+ <command id="cmd_editLink" oncommand="goDoCommand('cmd_editLink')"/>
+
+ <!-- dummy command used just to disable things in non-HTML modes -->
+ <command id="cmd_renderedHTMLEnabler"/>
+ </commandset>
+
+ <commandset id="composerSaveMenuItems"
+ commandupdater="true"
+ events="create, save"
+ oncommandupdate="goUpdateComposerMenuItems(this)"
+ >
+ <command id="cmd_save" label="&saveCmd.label;" oncommand="goDoCommand('cmd_save')"/>
+ <command id="cmd_saveAs" label="&saveAsCmd.label;" oncommand="goDoCommand('cmd_saveAs')"/>
+ <command id="cmd_exportToText" label="&exportToTextCmd.label;" oncommand="goDoCommand('cmd_exportToText')"/>
+ <command id="cmd_saveAndChangeEncoding" label="&saveAsChangeEncodingCmd.label;" oncommand="goDoCommand('cmd_saveAndChangeEncoding')"/>
+ <command id="cmd_publish" label="&publishCmd.label;" oncommand="goDoCommand('cmd_publish')"/>
+ <command id="cmd_publishAs" label="&publishAsCmd.label;" oncommand="goDoCommand('cmd_publishAs')"/>
+ <command id="cmd_revert" label="&fileRevert.label;" oncommand="goDoCommand('cmd_revert')"/>
+ <command id="cmd_preview" oncommand="goDoCommand('cmd_preview')"/>
+ <command id="cmd_editSendPage" label="&sendPageCmd.label;"
+ accesskey="&sendPage.accesskey;" oncommand="goDoCommand('cmd_editSendPage')"/>
+ </commandset>
+
+
+ <!-- edit menu commands. These get updated by code in globalOverlay.js -->
+ <commandset id="composerEditMenuItems"
+ commandupdater="true"
+ events="create, mode_switch"
+ oncommandupdate="goUpdateComposerMenuItems(this)"
+ >
+ <command id="cmd_undo"/>
+ <command id="cmd_redo"/>
+ <command id="cmd_cut"/>
+ <command id="cmd_copy"/>
+ <command id="cmd_paste"/>
+ <command id="cmd_pasteNoFormatting" oncommand="goDoCommand('cmd_pasteNoFormatting')"
+ label="&pasteNoFormatting.label;" accesskey="&pasteNoFormatting.accesskey;"/>
+ <command id="cmd_delete"/>
+ <command id="cmd_selectAll"/>
+ <command id="cmd_preferences" oncommand="goDoCommand('cmd_preferences')"/>
+ <command id="cmd_find" oncommand="goDoCommand('cmd_find')"/>
+ <command id="cmd_findNext" oncommand="goDoCommand('cmd_findNext')" label="&findAgainCmd.label;"/>
+ <command id="cmd_findPrev" oncommand="goDoCommand('cmd_findPrev')" label="&findPrevCmd.label;"/>
+ <command id="cmd_spelling" oncommand="goDoCommand('cmd_spelling')"/>
+ <command id="cmd_validate" label="&validateCmd.label;" accesskey="&validate.accesskey;" oncommand="goDoCommand('cmd_validate')"/>
+ <command id="cmd_checkLinks" oncommand="goDoCommand('cmd_checkLinks')"/>
+ <command id="cmd_pasteQuote" oncommand="goDoCommand('cmd_pasteQuote')" label="&pasteAsQuotationCmd.label;"/>
+ <command id="cmd_publishSettings" label="&publishSettings.label;" accesskey="&publishSettings.accesskey;" oncommand="goDoCommand('cmd_publishSettings')"/>
+ </commandset>
+
+ <!-- style related commands that update on creation, and on selection change -->
+ <commandset id="composerStyleMenuItems"
+ commandupdater="true"
+ events="create, style, mode_switch"
+ oncommandupdate="goUpdateComposerMenuItems(this)"
+ >
+ <command id="cmd_bold" state="false" oncommand="doStyleUICommand('cmd_bold')"/>
+ <command id="cmd_italic" state="false" oncommand="doStyleUICommand('cmd_italic')"/>
+ <command id="cmd_underline" state="false" oncommand="doStyleUICommand('cmd_underline')"/>
+ <command id="cmd_tt" state="false" oncommand="doStyleUICommand('cmd_tt')"/>
+ <command id="cmd_smiley"/>
+
+ <command id="cmd_strikethrough" state="false" oncommand="doStyleUICommand('cmd_strikethrough');"/>
+ <command id="cmd_superscript" state="false" oncommand="doStyleUICommand('cmd_superscript');"/>
+ <command id="cmd_subscript" state="false" oncommand="doStyleUICommand('cmd_subscript');"/>
+ <command id="cmd_nobreak" state="false" oncommand="doStyleUICommand('cmd_nobreak');"/>
+
+ <command id="cmd_em" state="false" oncommand="doStyleUICommand('cmd_em')"/>
+ <command id="cmd_strong" state="false" oncommand="doStyleUICommand('cmd_strong')"/>
+ <command id="cmd_cite" state="false" oncommand="doStyleUICommand('cmd_cite')"/>
+ <command id="cmd_abbr" state="false" oncommand="doStyleUICommand('cmd_abbr')"/>
+ <command id="cmd_acronym" state="false" oncommand="doStyleUICommand('cmd_acronym')"/>
+ <command id="cmd_code" state="false" oncommand="doStyleUICommand('cmd_code')"/>
+ <command id="cmd_samp" state="false" oncommand="doStyleUICommand('cmd_samp')"/>
+ <command id="cmd_var" state="false" oncommand="doStyleUICommand('cmd_var')"/>
+
+ <command id="cmd_ul" state="false" oncommand="doStyleUICommand('cmd_ul')"/>
+ <command id="cmd_ol" state="false" oncommand="doStyleUICommand('cmd_ol')"/>
+
+ <command id="cmd_indent" oncommand="goDoCommand('cmd_indent')"/>
+ <command id="cmd_outdent" oncommand="goDoCommand('cmd_outdent')"/>
+
+ <!-- the state attribute gets filled with the paragraph format before the command is exectued -->
+ <command id="cmd_paragraphState" state="" oncommand="doStatefulCommand('cmd_paragraphState', event.target.value)"/>
+ <command id="cmd_fontFace" state="" oncommand="doStatefulCommand('cmd_fontFace', event.target.value)"/>
+
+ <!-- No "oncommand", use EditorSelectColor() to bring up color dialog -->
+ <command id="cmd_fontColor" state=""/>
+ <command id="cmd_backgroundColor" state=""/>
+ <command id="cmd_highlight" state="transparent" oncommand="EditorSelectColor('Highlight', event);"/>
+
+ <command id="cmd_fontSize" oncommand="goDoCommand('cmd_fontSize')"/>
+ <command id="cmd_align" state=""/>
+
+ <command id="cmd_absPos" state="" oncommand="goDoCommand('cmd_absPos')"/>
+ <command id="cmd_increaseZIndex" state="" oncommand="goDoCommand('cmd_increaseZIndex')"/>
+ <command id="cmd_decreaseZIndex" state="" oncommand="goDoCommand('cmd_decreaseZIndex')"/>
+
+ <command id="cmd_advancedProperties" oncommand="goDoCommand('cmd_advancedProperties')"/>
+
+ <command id="cmd_increaseFont" oncommand="goDoCommand('cmd_increaseFont')"/>
+ <command id="cmd_decreaseFont" oncommand="goDoCommand('cmd_decreaseFont')"/>
+
+ <command id="cmd_removeStyles" oncommand="goDoCommand('cmd_removeStyles')"/>
+ <command id="cmd_removeLinks" oncommand="goDoCommand('cmd_removeLinks')"/>
+ <command id="cmd_removeNamedAnchors" oncommand="goDoCommand('cmd_removeNamedAnchors')"/>
+ <command id="cmd_updateStructToolbar" oncommand="goDoCommand('cmd_updateStructToolbar')"/>
+ </commandset>
+
+ <!-- commands updated only when the menu gets created -->
+ <commandset id="composerListMenuItems"
+ commandupdater="true"
+ events="create, mode_switch"
+ oncommandupdate="goUpdateComposerMenuItems(this)">
+ <!-- List menu -->
+ <command id="cmd_dt" oncommand="doStyleUICommand('cmd_dt')"/>
+ <command id="cmd_dd" oncommand="doStyleUICommand('cmd_dd')"/>
+ <command id="cmd_removeList" oncommand="goDoCommand('cmd_removeList')"/>
+ <!-- cmd_ul and cmd_ol are shared with toolbar and are in composerStyleMenuItems commandset -->
+ </commandset>
+
+ <commandset id="composerTableMenuItems"
+ commandupdater="true"
+ events="create, mode_switch"
+ oncommandupdate="goUpdateTableMenuItems(this)">
+ <!-- Table menu -->
+ <command id="cmd_SelectTable" oncommand="goDoCommand('cmd_SelectTable')"/>
+ <command id="cmd_SelectRow" oncommand="goDoCommand('cmd_SelectRow')"/>
+ <command id="cmd_SelectColumn" oncommand="goDoCommand('cmd_SelectColumn')"/>
+ <command id="cmd_SelectCell" oncommand="goDoCommand('cmd_SelectCell')"/>
+ <command id="cmd_SelectAllCells" oncommand="goDoCommand('cmd_SelectAllCells')"/>
+ <command id="cmd_InsertTable" oncommand="goDoCommand('cmd_InsertTable')"/>
+ <command id="cmd_InsertRowAbove" oncommand="goDoCommand('cmd_InsertRowAbove')"/>
+ <command id="cmd_InsertRowBelow" oncommand="goDoCommand('cmd_InsertRowBelow')"/>
+ <command id="cmd_InsertColumnBefore" oncommand="goDoCommand('cmd_InsertColumnBefore')"/>
+ <command id="cmd_InsertColumnAfter" oncommand="goDoCommand('cmd_InsertColumnAfter')"/>
+ <command id="cmd_InsertCellBefore" oncommand="goDoCommand('cmd_InsertCellBefore')"/>
+ <command id="cmd_InsertCellAfter" oncommand="goDoCommand('cmd_InsertCellAfter')"/>
+ <command id="cmd_DeleteTable" oncommand="goDoCommand('cmd_DeleteTable')"/>
+ <command id="cmd_DeleteRow" oncommand="goDoCommand('cmd_DeleteRow')"/>
+ <command id="cmd_DeleteColumn" oncommand="goDoCommand('cmd_DeleteColumn')"/>
+ <command id="cmd_DeleteCell" oncommand="goDoCommand('cmd_DeleteCell')"/>
+ <command id="cmd_DeleteCellContents" oncommand="goDoCommand('cmd_DeleteCellContents')"/>
+ <command id="cmd_NormalizeTable" oncommand="goDoCommand('cmd_NormalizeTable')"/>
+ <command id="cmd_JoinTableCells" oncommand="goDoCommand('cmd_JoinTableCells')"/>
+ <command id="cmd_SplitTableCell" oncommand="goDoCommand('cmd_SplitTableCell')"/>
+ <command id="cmd_ConvertToTable" oncommand="goDoCommand('cmd_ConvertToTable')"/>
+ <command id="cmd_TableOrCellColor" oncommand="goDoCommand('cmd_TableOrCellColor')"/>
+ <command id="cmd_editTable" oncommand="goDoCommand('cmd_editTable')"/>
+ </commandset>
+
+ <broadcasterset id="broadcasterset">
+ <!-- Broadcasters/commands with no other home -->
+ <!-- view menu -->
+ <command id="cmd_newNavigator"/>
+ <command id="cmd_newEditor"/>
+ <command id="cmd_newEditorTemplate"/>
+ <command id="cmd_newEditorDraft"/>
+
+ <command id="cmd_viewCompToolbar" oncommand="goToggleToolbar('EditToolbar','cmd_viewCompToolbar');" checked="true"/>
+ <command id="cmd_viewFormatToolbar" oncommand="goToggleToolbar('FormatToolbar','cmd_viewFormatToolbar');" checked="true"/>
+ <command id="cmd_viewEditModeToolbar" oncommand="goToggleToolbar('EditModeToolbar','cmd_viewEditModeToolbar');" checked="true"/>
+
+ <!-- Obsolete; these will go away -->
+ <command id="Editor:Font:Size" fontsize=""/>
+ </broadcasterset>
+
+ <!-- File menu items -->
+ <!-- Note: globalOverlay.xul uses menu_newEditor, but we want different menu item text
+ so we use our own id, label, and accesskey but connect to the same global key and broadcaster node
+ -->
+ <menu id="fileMenu" label="&fileMenu.label;" accesskey="&filemenu.accesskey;">
+ <menupopup id="menu_FilePopup" onpopupshowing="EditorInitFileMenu();">
+ <menu id="menu_New">
+ <menupopup id="menu_NewPopup">
+ <menuitem id="menu_newBlankPage" label="&newBlankPageCmd.label;"
+ accesskey="&newBlankPage.accesskey;" key="key_newBlankPage"
+ command="cmd_newEditor"/>
+ <menuseparator id="composerBeginGlobalNewItems"/>
+ <!-- From globalOverlay.xul -->
+ <menuitem id="menu_newNavigator" observes="cmd_newNavigator"/>
+ </menupopup>
+ </menu>
+ <menuitem accesskey="&fileopenremote.accesskey;" key="openremoteeditorkb" observes="cmd_openRemote"/>
+ <menuitem accesskey="&fileopen.accesskey;" key="openeditorkb" observes="cmd_open" label="&openFileCmd.label;"/>
+ <menu id="menu_RecentFiles" accesskey="&filerecentmenu.accesskey;" label="&fileRecentMenu.label;"
+ onpopupshowing="BuildRecentPagesMenu();">
+ <menupopup id="menupopup_RecentFiles" oncommand="editPage(event.target.getAttribute('value'), window, false);"/>
+ <!-- menuitems appended at runtime -->
+ </menu>
+ <menuitem accesskey="&fileclose.accesskey;" key="closekb" observes="cmd_close"/>
+ <menuseparator/>
+ <menuitem id="saveMenuitem" accesskey="&filesave.accesskey;" key="savekb" observes="cmd_save"/>
+ <menuitem accesskey="&filesaveas.accesskey;" observes="cmd_saveAs"/>
+ <menuitem accesskey="&filesaveandchangeencoding.accesskey;" observes="cmd_saveAndChangeEncoding"/>
+ <menuseparator/>
+ <menuitem id="publishMenuitem" accesskey="&publishcmd.accesskey;" key="publishkb" observes="cmd_publish"/>
+ <menuitem accesskey="&publishas.accesskey;" observes="cmd_publishAs"/>
+ <menuseparator/>
+ <menuitem accesskey="&filerevert.accesskey;" observes="cmd_revert"/>
+ <menuseparator/>
+ <menuitem id="fileExportToText" accesskey="&fileexporttotext.accesskey;" observes="cmd_exportToText"/>
+ <menuitem id="previewInBrowser" label="&previewCmd.label;" accesskey="&filepreview.accesskey;" observes="cmd_preview"/>
+ <!-- menuitem id="menu_SendPage" is merged here from mailEditorOverlay.xul,
+ where "position" is assumed to be just after 'previewInBrowser' -->
+ <menuitem id="printSetupMenuItem" accesskey="&fileprintsetup.accesskey;" label="&printSetupCmd.label;" command="cmd_printSetup"/>
+ <menuitem id="printMenuItem" accesskey="&fileprint.accesskey;" key="printkb" observes="cmd_print" label="&printCmd.label;"/>
+ <!-- The Exit/Quit item is merged from platformGlobalOverlay.xul -->
+ </menupopup>
+ </menu>
+
+ <menu id="editMenu" label="&editMenu.label;" accesskey="&editmenu.accesskey;">
+ <menupopup id="edEditMenuPopup">
+ <!-- from utilityOverlay.xul -->
+ <menuitem id="menu_undo"/>
+ <menuitem id="menu_redo"/>
+ <menuseparator id="edEditMenuSep1" />
+ <menuitem id="menu_cut"/>
+ <menuitem id="menu_copy"/>
+ <menuitem id="menu_paste"/>
+ <menuitem id="menu_pasteNoFormatting" observes="cmd_pasteNoFormatting"/>
+
+<!-- PasteAs not implemented yet
+ <menu id="menu_pasteAs" label="&pasteAs.label;" accesskey="&pasteAs.accesskey;">
+ <menupopup onpopupshowing="InitPasteAsMenu();">
+ <menuitem id="menu_pasteText" label="&pasteTextCmd.label;" accesskey="&pasteText.accesskey;"/>
+ <menuitem id="menu_pasteImage" label="&pasteImageCmd.label;" accesskey="&pasteImage.accesskey;"/>
+ <menuseparator/>
+ <menuitem id="menu_pasteRows" label="&pasteRowsCmd.label;" accesskey="&pasteRows.accesskey;"/>
+ <menuitem id="menu_pasteColumns" label="&pasteColumnsCmd.label;" accesskey="&pasteColumns.accesskey;"/>
+ <menuitem id="menu_pasteTable" accesskey="&pasteTable.accesskey;"/>
+ </menupopup>
+ </menu>
+-->
+ <menuitem id="menu_delete"/>
+ <menuseparator id="edEditMenuSep2" />
+ <menuitem id="menu_selectAll"/>
+ <menuseparator id="sep_find"/>
+ <menuitem id="menu_find" accesskey="&editfind.accesskey;" key="findkb" observes="cmd_find" label="&findCmd.label;"/>
+ <menuitem id="menu_findnext" accesskey="&editfindnext.accesskey;" key="findnextkb" observes="cmd_findNext"/>
+ <menuitem id="menu_findprev" accesskey="&editfindprev.accesskey;" key="findprevkb" observes="cmd_findPrev"/>
+ <menuseparator id="sep_checkspelling"/>
+ <menuitem id="menu_checkspelling" accesskey="&editcheckspelling.accesskey;"
+ key="checkspellingkb" observes="cmd_spelling" disabled="true"
+ label="&checkSpellingCmd.label;"/>
+ <menuitem id="menu_inlinespellcheck" type="checkbox"
+ label="&enableInlineSpellChecker.label;"
+ accesskey="&enableInlineSpellChecker.accesskey;"
+ oncommand="InlineSpellCheckerUI.enabled = !InlineSpellCheckerUI.enabled"/>
+ <menuseparator id="menu_prefsSep"/>
+ <menuitem id="menu_preferences" observes="cmd_preferences"/>
+ <!-- Note: other Edit items (menu_validate, menu_publishSettings) are inserted from composerOverlay.xul -->
+ </menupopup>
+ </menu>
+
+ <menuitem id="viewNormalMode" type="radio" group="mode" accesskey="&NormalMode.accesskey;" observes="cmd_NormalMode"/>
+ <menuitem id="viewAllTagsMode" type="radio" group="mode" accesskey="&AllTagsMode.accesskey;" observes="cmd_AllTagsMode"/>
+ <menuitem id="viewSourceMode" type="radio" group="mode" accesskey="&HTMLSourceMode.accesskey;" observes="cmd_HTMLSourceMode" label="&HTMLSourceMode.label;"/>
+ <menuitem id="viewPreviewMode" type="radio" group="mode" accesskey="&PreviewMode.accesskey;" observes="cmd_PreviewMode"/>
+
+ <menupopup id = "composerCharsetMenuPopup" onpopupshowing="updateCharsetPopupMenu(this)" />
+
+ <!-- Insert menu -->
+ <menu id="insertMenu" label="&insertMenu.label;" accesskey="&insertmenu.accesskey;">
+ <menupopup id="insertMenuPopup">
+ <menuitem id="insertImage" accesskey="&insertimage.accesskey;" observes="cmd_image" label="&insertImageCmd.label;"/>
+ <menuitem id="insertTable" accesskey="&inserttable.accesskey;" observes="cmd_InsertTable" label="&insertTableCmd.label;"/>
+ <menuitem id="insertLink" accesskey="&insertlink.accesskey;" observes="cmd_link" label="&insertLinkCmd.label;" key="insertlinkkb"/>
+ <menuitem id="insertAnchor" accesskey="&insertanchor.accesskey;" observes="cmd_anchor" label="&insertAnchorCmd.label;"/>
+ <menuitem id="insertHline" accesskey="&inserthline.accesskey;" observes="cmd_hline" label="&insertHLineCmd.label;"/>
+ <menuitem id="insertHTMLSource" accesskey="&insertHTMLCmd.accesskey;" observes="cmd_insertHTMLWithDialog" key="inserthtmlkb"/>
+ <menuitem accesskey="&insertchars.accesskey;" observes="cmd_insertChars" id="insertChars"/>
+ <menu id="insertTOC" label="&tocMenu.label;" accesskey="&tocMenu.accesskey;">
+ <menupopup onpopupshowing="InitTOCMenu()">
+ <menuitem id="insertTOCMenuitem"
+ label="&insertTOC.label;"
+ accesskey="&insertTOC.accesskey;"
+ oncommand="UpdateTOC()"/>
+ <menuitem id="updateTOCMenuitem"
+ label="&updateTOC.label;"
+ accesskey="&updateTOC.accesskey;"
+ oncommand="UpdateTOC()"/>
+ <menuitem id="removeTOCMenuitem"
+ label="&removeTOC.label;"
+ accesskey="&removeTOC.accesskey;"
+ oncommand="RemoveTOC()"/>
+ </menupopup>
+ </menu>
+ <menuseparator id="insertMenuSeparator"/>
+<!-- Activate this after Enter key inserts P tag and not BR
+ <menuitem accesskey="&insertbreak.accesskey;" observes="cmd_insertBreak" label="&insertBreakCmd.label;"/>
+-->
+ <menuitem id="insertBreakAll" accesskey="&insertbreakall.accesskey;" observes="cmd_insertBreakAll" label="&insertBreakAllCmd.label;"/>
+ </menupopup>
+ </menu>
+
+ <!-- Insert menu for PlainText editor -->
+ <menu id="insertMenuPlainText" label="&insertMenu.label;" accesskey="&insertmenu.accesskey;">
+ <menupopup>
+ <menuitem accesskey="&insertchars.accesskey;" observes="cmd_insertChars" />
+ </menupopup>
+ </menu>
+
+ <!-- Format Menu -->
+ <menupopup id="formatMenuPopup" onpopupshowing="EditorInitFormatMenu()">
+ <!-- Font face submenu -->
+ <menu id="fontFaceMenu" label="&fontfaceMenu.label;" accesskey="&formatfontmenu.accesskey;"
+ position="1">
+ <menupopup oncommand="if (event.target.localName == 'menuitem')
+ doStatefulCommand('cmd_fontFace', event.target.getAttribute('value'));"
+ onpopupshowing="initFontFaceMenu(this);">
+ <menuitem label="&fontVarWidth.label;" accesskey="&fontvarwidth.accesskey;" value="" type="radio" name="1" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&fontFixedWidth.label;" accesskey="&fontfixedwidth.accesskey;" value="tt" type="radio" name="1" observes="cmd_renderedHTMLEnabler"/>
+ <menuseparator/>
+ <menuitem label="&fontHelveticaFont.label;" accesskey="&fonthelvetica.accesskey;" value="Helvetica, Arial, sans-serif" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&fontTimes.label;" accesskey="&fonttimes.accesskey;" value="Times New Roman, Times, serif" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&fontCourier.label;" accesskey="&fontcourier.accesskey;" value="Courier New, Courier, monospace" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuseparator/>
+ <!-- Local font face items added here by initLocalFontFaceMenu() -->
+ </menupopup>
+ </menu>
+
+ <!-- Font size submenu -->
+ <menu id="fontSizeMenu" label="&fontsizeMenu.label;"
+ accesskey="&formatsizemenu.accesskey;"
+ position="2">
+ <menupopup onpopupshowing="initFontSizeMenu(this)">
+ <menuitem label="&decreaseFontSize.label;" accesskey="&decreasefontsize.accesskey;" observes="cmd_decreaseFont" type="radio" name="1" key="decreasefontsizekb"/>
+ <menuitem label="&increaseFontSize.label;" accesskey="&increasefontsize.accesskey;" observes="cmd_increaseFont" type="radio" name="1" key="increasefontsizekb"/>
+ <menuseparator/>
+<!-- Not supported in current font size implementation
+ <menuitem label="&size-xx-smallCmd.label;" accesskey="&size-xx-small.accesskey;" oncommand="EditorSetFontSize('xx-small')" type="radio" name="2" />
+-->
+ <menuitem label="&size-x-smallCmd.label;" accesskey="&size-x-small.accesskey;" oncommand="EditorSetFontSize('x-small')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&size-smallCmd.label;" accesskey="&size-small.accesskey;" oncommand="EditorSetFontSize('small')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&size-mediumCmd.label;" accesskey="&size-medium.accesskey;" oncommand="EditorSetFontSize('medium')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&size-largeCmd.label;" accesskey="&size-large.accesskey;" oncommand="EditorSetFontSize('large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&size-x-largeCmd.label;" accesskey="&size-x-large.accesskey;" oncommand="EditorSetFontSize('x-large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem label="&size-xx-largeCmd.label;" accesskey="&size-xx-large.accesskey;" oncommand="EditorSetFontSize('xx-large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
+ </menupopup>
+ </menu>
+
+ <!-- Font style submenu -->
+ <menu id="fontStyleMenu" label="&fontStyleMenu.label;"
+ accesskey="&formatstylemenu.accesskey;"
+ position="3">
+ <menupopup onpopupshowing="initFontStyleMenu(this)">
+ <menuitem label="&styleBoldCmd.label;" accesskey="&stylebold.accesskey;" observes="cmd_bold" type="checkbox" key="boldkb"/>
+ <menuitem label="&styleItalicCmd.label;" accesskey="&styleitalic.accesskey;" observes="cmd_italic" type="checkbox" key="italickb" />
+ <menuitem label="&styleUnderlineCmd.label;" accesskey="&styleunderline.accesskey;" observes="cmd_underline" type="checkbox" key="underlinekb"/>
+ <menuitem label="&styleStrikeThruCmd.label;" accesskey="&stylestrikethru.accesskey;" observes="cmd_strikethrough" type="checkbox"/>
+ <menuitem label="&styleSuperscriptCmd.label;" accesskey="&stylesuperscript.accesskey;" observes="cmd_superscript" type="checkbox"/>
+ <menuitem label="&styleSubscriptCmd.label;" accesskey="&stylesubscript.accesskey;" observes="cmd_subscript" type="checkbox"/>
+ <menuitem label="&fontFixedWidth.label;" accesskey="&fontfixedwidth.accesskey;" observes="cmd_tt" type="checkbox" key="fixedwidthkb"/>
+ <menuitem label="&styleNonbreakingCmd.label;" accesskey="&stylenonbreaking.accesskey;" observes="cmd_nobreak" type="checkbox"/>
+ <menuseparator/>
+ <menuitem label="&styleEm.label;" accesskey="&styleEm.accesskey;" observes="cmd_em" type="checkbox"/>
+ <menuitem label="&styleStrong.label;" accesskey="&styleStrong.accesskey;" observes="cmd_strong" type="checkbox"/>
+ <menuitem label="&styleCite.label;" accesskey="&styleCite.accesskey;" observes="cmd_cite" type="checkbox"/>
+ <menuitem label="&styleAbbr.label;" accesskey="&styleAbbr.accesskey;" observes="cmd_abbr" type="checkbox"/>
+ <menuitem label="&styleAcronym.label;" accesskey="&styleAcronym.accesskey;" observes="cmd_acronym" type="checkbox"/>
+ <menuitem label="&styleCode.label;" accesskey="&styleCode.accesskey;" observes="cmd_code" type="checkbox"/>
+ <menuitem label="&styleSamp.label;" accesskey="&styleSamp.accesskey;" observes="cmd_samp" type="checkbox"/>
+ <menuitem label="&styleVar.label;" accesskey="&styleVar.accesskey;" observes="cmd_var" type="checkbox"/>
+ </menupopup>
+ </menu>
+
+ <!-- Note: "cmd_fontColor" only monitors color state, it doesn't execute the command
+ (We should use "cmd_fontColorState" and "cmd_backgroundColorState" ?) -->
+ <menuitem id="fontColor" label="&formatFontColor.label;"
+ accesskey="&formatfontcolor.accesskey;"
+ observes="cmd_fontColor"
+ oncommand="EditorSelectColor('Text', null);"
+ position="4"/>
+ <menuseparator id="removeSep" position="5"/>
+
+ <!-- label and accesskey set at runtime from strings -->
+ <menuitem id="removeStylesMenuitem" key="removestyleskb"
+ observes="cmd_removeStyles"
+ position="6"/>
+ <menuitem id="removeLinksMenuitem" key="removelinkskb"
+ observes="cmd_removeLinks"
+ position="7"/>
+ <menuitem id="removeNamedAnchorsMenuitem" label="&formatRemoveNamedAnchors.label;"
+ key="removenamedanchorskb"
+ accesskey="&formatRemoveNamedAnchors.accesskey;"
+ observes="cmd_removeNamedAnchors"
+ position="8"/>
+ <menuseparator id="tabSep" position="9"/>
+
+ <!-- Note: the 'Init' menu methods for Paragraph, List, and Align
+ assume that the id = 'menu_'+tagName (the 'value' label),
+ except for the first ('none') item
+ -->
+ <!-- Paragraph Style submenu -->
+ <menu id="paragraphMenu" label="¶graphMenu.label;"
+ accesskey="&formatparagraphmenu.accesskey;"
+ position="10" onpopupshowing="InitParagraphMenu()">
+ <menupopup oncommand="doStatefulCommand('cmd_paragraphState', event.target.getAttribute('value'))">
+ <menuitem id="menu_bodyText" type="radio" name="1" label="&bodyTextCmd.label;" accesskey="&bodytext.accesskey;" value="" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_p" type="radio" name="1" label="¶graphParagraphCmd.label;" accesskey="¶graphparagraph.accesskey;" value="p" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h1" type="radio" name="1" label="&heading1Cmd.label;" accesskey="&heading1.accesskey;" value="h1" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h2" type="radio" name="1" label="&heading2Cmd.label;" accesskey="&heading2.accesskey;" value="h2" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h3" type="radio" name="1" label="&heading3Cmd.label;" accesskey="&heading3.accesskey;" value="h3" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h4" type="radio" name="1" label="&heading4Cmd.label;" accesskey="&heading4.accesskey;" value="h4" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h5" type="radio" name="1" label="&heading5Cmd.label;" accesskey="&heading5.accesskey;" value="h5" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_h6" type="radio" name="1" label="&heading6Cmd.label;" accesskey="&heading6.accesskey;" value="h6" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_address" type="radio" name="1" label="¶graphAddressCmd.label;" accesskey="¶graphaddress.accesskey;" value="address" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_pre" type="radio" name="1" label="¶graphPreformatCmd.label;" accesskey="¶graphpreformat.accesskey;" value="pre" observes="cmd_renderedHTMLEnabler"/>
+ </menupopup>
+ </menu>
+
+ <!-- List Style submenu -->
+ <menu id="listMenu" label="&formatlistMenu.label;"
+ accesskey="&formatlistmenu.accesskey;"
+ position="11" onpopupshowing="InitListMenu()">
+ <menupopup>
+ <menuitem id="menu_noList" type="radio" name="1" label="&noneCmd.label;" accesskey="&none.accesskey;" observes="cmd_removeList"/>
+ <menuitem id="menu_ul" type="radio" name="1" label="&listBulletCmd.label;" accesskey="&listbullet.accesskey;" observes="cmd_ul"/>
+ <menuitem id="menu_ol" type="radio" name="1" label="&listNumberedCmd.label;" accesskey="&listnumbered.accesskey;" observes="cmd_ol"/>
+ <menuitem id="menu_dt" type="radio" name="1" label="&listTermCmd.label;" accesskey="&listterm.accesskey;" observes="cmd_dt"/>
+ <menuitem id="menu_dd" type="radio" name="1" label="&listDefinitionCmd.label;" accesskey="&listdefinition.accesskey;" observes="cmd_dd"/>
+ <menuseparator/>
+ <menuitem id="listProps" label="&listProps.label;" accesskey="&listprops.accesskey;" observes="cmd_listProperties"/>
+ </menupopup>
+ </menu>
+ <menuseparator id="identingSep" position="12"/>
+
+ <menuitem id="increaseIndent" label="&increaseIndent.label;" accesskey="&increaseindent.accesskey;" key="increaseindentkb"
+ observes="cmd_indent" position="13"/>
+ <menuitem id="decreaseIndent" label="&decreaseIndent.label;" accesskey="&decreaseindent.accesskey;" key="decreaseindentkb"
+ observes="cmd_outdent" position="14"/>
+
+ <menu id="alignMenu" label="&alignMenu.label;" accesskey="&formatalignmenu.accesskey;"
+ onpopupshowing="InitAlignMenu()"
+ position="15">
+ <!-- Align submenu -->
+ <menupopup oncommand="doStatefulCommand('cmd_align', event.target.getAttribute('value'))">
+ <menuitem id="menu_left" label="&alignLeft.label;" accesskey="&alignleft.accesskey;" type="radio" name="1" value="left" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_center" label="&alignCenter.label;" accesskey="&aligncenter.accesskey;" type="radio" name="1" value="center" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_right" label="&alignRight.label;" accesskey="&alignright.accesskey;" type="radio" name="1" value="right" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="menu_justify" label="&alignJustify.label;" accesskey="&alignjustify.accesskey;" type="radio" name="1" value="justify" observes="cmd_renderedHTMLEnabler"/>
+ </menupopup>
+ </menu>
+ <menuseparator id="tableSep" position="16"/>
+ <!-- Merge Table Menu and separator in Messenger Composer here -->
+ <!-- Merge property items here -->
+ </menupopup>
+
+ <menuitem id="snapToGrid" label="&grid.label;" accesskey="&grid.accesskey;"
+ oncommand="goDoCommand('cmd_grid')" observes="cmd_renderedHTMLEnabler"/>
+
+ <!-- Next 3 are items to append at the bottom of the formatMenuPopup -->
+ <!-- label and accesskey filled in during menu creation -->
+ <menuitem id="objectProperties" oncommand="goDoCommand('cmd_objectProperties')" observes="cmd_renderedHTMLEnabler"/>
+ <!-- Don't use 'observes', must call command correctly -->
+ <menuitem id="pageProperties" label="&pageProperties.label;" accesskey="&pageproperties.accesskey;"
+ oncommand="goDoCommand('cmd_pageProperties')" observes="cmd_renderedHTMLEnabler"/>
+ <menuitem id="colorsAndBackground" label="&colorsAndBackground.label;" accesskey="&colorsandbackground.accesskey;"
+ oncommand="goDoCommand('cmd_colorProperties')" observes="cmd_renderedHTMLEnabler"/>
+
+ <menu id="tableMenu" label="&tableMenu.label;" accesskey="&tablemenu.accesskey;">
+ <menupopup onpopupshowing="EditorInitTableMenu()">
+ <!-- From EditorCommandOverlay.xul (shared with context popup) -->
+ <menu id="tableInsertMenu" label="&tableInsertMenu.label;" accesskey="&tableinsertmenu.accesskey;">
+ <menupopup>
+ <menuitem label="&insertTableCmd.label;" accesskey="&tabletable.accesskey;" observes="cmd_InsertTable"/>
+ <menuseparator />
+ <menuitem label="&tableRowAbove.label;" accesskey="&tablerow.accesskey;" observes="cmd_InsertRowAbove"/>
+ <menuitem label="&tableRowBelow.label;" accesskey="&tablerowbelow.accesskey;" observes="cmd_InsertRowBelow"/>
+ <menuseparator />
+ <menuitem label="&tableColumnBefore.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_InsertColumnBefore"/>
+ <menuitem label="&tableColumnAfter.label;" accesskey="&tablecolumnafter.accesskey;" observes="cmd_InsertColumnAfter"/>
+ <menuseparator />
+ <menuitem label="&tableCellBefore.label;" accesskey="&tablecell.accesskey;" observes="cmd_InsertCellBefore"/>
+ <menuitem label="&tableCellAfter.label;" accesskey="&tablecellafter.accesskey;" observes="cmd_InsertCellAfter"/>
+ </menupopup>
+ </menu>
+ <menu id="tableSelectMenu" label="&tableSelectMenu.label;" accesskey="&tableselectmenu.accesskey;">
+ <menupopup id="tableSelectPopup">
+ <menuitem id="menu_SelectTable" label="&tableTable.label;" accesskey="&tabletable.accesskey;" observes="cmd_SelectTable" />
+ <menuitem id="menu_SelectRow" label="&tableRow.label;" accesskey="&tablerow.accesskey;" observes="cmd_SelectRow" />
+ <menuitem id="menu_SelectColumn" label="&tableColumn.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_SelectColumn" />
+ <menuitem id="menu_SelectCell" label="&tableCell.label;" accesskey="&tablecell.accesskey;" observes="cmd_SelectCell" />
+ <menuitem id="menu_SelectAllCells" label="&tableAllCells.label;" accesskey="&tableallcells.accesskey;" observes="cmd_SelectAllCells" />
+ </menupopup>
+ </menu>
+ <menu id="tableDeleteMenu" label="&tableDeleteMenu.label;" accesskey="&tabledeletemenu.accesskey;">
+ <menupopup id="tableDeletePopup">
+ <menuitem id="menu_DeleteTable" label="&tableTable.label;" accesskey="&tabletable.accesskey;" observes="cmd_DeleteTable"/>
+ <menuitem id="menu_DeleteRow" label="&tableRows.label;" accesskey="&tablerow.accesskey;" observes="cmd_DeleteRow"/>
+ <menuitem id="menu_DeleteColumn" label="&tableColumns.label;" accesskey="&tablecolumn.accesskey;" observes="cmd_DeleteColumn"/>
+ <menuitem id="menu_DeleteCell" label="&tableCells.label;" accesskey="&tablecell.accesskey;" observes="cmd_DeleteCell"/>
+ <menuitem id="menu_DeleteCellContents" label="&tableCellContents.label;" accesskey="&tablecellcontents.accesskey;" observes="cmd_DeleteCellContents"/>
+ </menupopup>
+ </menu>
+ <menuseparator />
+ <!-- menu label is set in InitTableMenu -->
+ <menuitem id="menu_JoinTableCells" label="&tableJoinCells.label;" accesskey="&tablejoincells.accesskey;" observes="cmd_JoinTableCells"/>
+ <menuitem id="menu_SlitTableCell" label="&tableSplitCell.label;" accesskey="&tablesplitcell.accesskey;" observes="cmd_SplitTableCell"/>
+ <menuitem id="menu_ConvertToTable" label="&convertToTable.label;" accesskey="&converttotable.accesskey;" observes="cmd_ConvertToTable"/>
+ <menuseparator />
+ <menuitem id="menu_TableOrCellColor" label="&tableOrCellColor.label;" accesskey="&tableOrCellColor.accesskey;" observes="cmd_TableOrCellColor"/>
+ <menuitem id="menu_tableProperties" label="&tableProperties.label;" accesskey="&tableProperties.accesskey;" observes="cmd_editTable"/>
+ </menupopup>
+ </menu>
+
+ <!-- this is only used in messengercompose.xul -->
+ <toolbarbutton type="menu" id="AlignPopupButton" observes="cmd_align"
+ tooltiptext="&AlignPopupButton.tooltip;">
+ <menupopup id="AlignPopup">
+ <menuitem id="AlignLeftItem" class="menuitem-iconic" label="&alignLeft.label;"
+ oncommand="doStatefulCommand('cmd_align', 'left')"
+ tooltiptext="&alignLeftButton.tooltip;" />
+ <menuitem id="AlignCenterItem" class="menuitem-iconic" label="&alignCenter.label;"
+ oncommand="doStatefulCommand('cmd_align', 'center')"
+ tooltiptext="&alignCenterButton.tooltip;" />
+ <menuitem id="AlignRightItem" class="menuitem-iconic" label="&alignRight.label;"
+ oncommand="doStatefulCommand('cmd_align', 'right')"
+ tooltiptext="&alignRightButton.tooltip;" />
+ <menuitem id="AlignJustifyItem" class="menuitem-iconic" label="&alignJustify.label;"
+ oncommand="doStatefulCommand('cmd_align', 'justify')"
+ tooltiptext="&alignjustifyButton.tooltip;" />
+ </menupopup>
+ </toolbarbutton>
+
+ <!-- InsertPopupButton is used by messengercompose.xul -->
+ <toolbarbutton type="menu" id="InsertPopupButton" observes="cmd_renderedHTMLEnabler"
+ tooltiptext="&InsertPopupButton.tooltip;">
+ <menupopup id="InsertPopup">
+ <menuitem id="InsertLinkItem" class="menuitem-iconic" observes="cmd_link"
+ oncommand="goDoCommand('cmd_link')" label="&linkToolbarCmd.label;"
+ tooltiptext="&linkToolbarCmd.tooltip;" />
+ <menuitem id="InsertAnchorItem" class="menuitem-iconic" observes="cmd_anchor"
+ oncommand="goDoCommand('cmd_anchor')" label="&anchorToolbarCmd.label;"
+ tooltiptext="&anchorToolbarCmd.tooltip;" />
+ <menuitem id="InsertImageItem" class="menuitem-iconic" observes="cmd_image"
+ oncommand="goDoCommand('cmd_image')" label="&imageToolbarCmd.label;"
+ tooltiptext="&imageToolbarCmd.tooltip;" />
+ <menuitem id="InsertHRuleItem" class="menuitem-iconic" observes="cmd_hline"
+ oncommand="goDoCommand('cmd_hline')" label="&hruleToolbarCmd.label;"
+ tooltiptext="&hruleToolbarCmd.tooltip;" />
+ <menuitem id="InsertTableItem" class="menuitem-iconic" observes="cmd_table"
+ oncommand="goDoCommand('cmd_table')" label="&tableToolbarCmd.label;"
+ tooltiptext="&tableToolbarCmd.tooltip;" />
+ </menupopup>
+ </toolbarbutton>
+
+ <!-- Editor toolbar items -->
+ <!-- note that we override the submenu item label "Blank Window" with "New" used for the menu -->
+ <toolbarbutton id="newButton" class="toolbarbutton-1"
+ label="&newMenu.label;" command="cmd_newEditor"
+ tooltiptext="&newToolbarCmd.tooltip;"/>
+ <toolbarbutton id="openButton" class="toolbarbutton-1"
+ label="&openToolbarCmd.label;" observes="cmd_open"
+ tooltiptext="&openToolbarCmd.tooltip;"/>
+ <toolbarbutton id="saveButton" class="toolbarbutton-1" observes="cmd_save"
+ tooltiptext="&saveToolbarCmd.tooltip;"/>
+ <toolbarbutton id="publishButton" class="toolbarbutton-1"
+ observes="cmd_publish"
+ tooltiptext="&publishToolbarCmd.tooltip;"/>
+ <toolbarbutton id="previewButton" class="toolbarbutton-1"
+ label="&previewToolbarCmd.label;" observes="cmd_preview"
+ tooltiptext="&previewToolbarCmd.tooltip;"/>
+ <toolbarbutton id="cutButton" class="toolbarbutton-1"
+ label="&cutCmd.label;" command="cmd_cut"
+ tooltiptext="&cutCmd.label;"/>
+ <toolbarbutton id="copyButton" class="toolbarbutton-1"
+ label="©Cmd.label;" command="cmd_copy"
+ tooltiptext="©Cmd.label;"/>
+ <toolbarbutton id="pasteButton" class="toolbarbutton-1"
+ label="&pasteCmd.label;" command="cmd_paste"
+ tooltiptext="&pasteCmd.label;"/>
+
+ <toolbarbutton id="printButton" type="menu-button" class="toolbarbutton-1"
+ label="&printToolbarCmd.label;"
+ tooltiptext="&printToolbarCmd.tooltip;"
+ oncommand="if (event.target==this) goDoCommand('cmd_print');">
+ <menupopup id="printMenu">
+ <menuitem id="printMenuItemToolbar" accesskey="&fileprint.accesskey;" label="&printCmd.label;" default="true"
+ oncommand="goDoCommand('cmd_print');"/>
+ <!-- 'printSetupToolbar' is merged in here from platformGlobalOverlay.xul -->
+ </menupopup>
+ </toolbarbutton>
+
+ <toolbarbutton id="findButton" class="toolbarbutton-1"
+ label="&findToolbarCmd.label;" observes="cmd_find"
+ tooltiptext="&findToolbarCmd.tooltip;"/>
+ <toolbarbutton id="spellingButton" class="toolbarbutton-1" disabled="true"
+ label="&spellToolbarCmd.label;" observes="cmd_spelling"
+ tooltiptext="&spellToolbarCmd.tooltip;"/>
+ <toolbarbutton id="imageButton" class="toolbarbutton-1"
+ label="&imageToolbarCmd.label;" observes="cmd_image"
+ tooltiptext="&imageToolbarCmd.tooltip;"/>
+ <toolbarbutton id="hlineButton" class="toolbarbutton-1"
+ label="&hruleToolbarCmd.label;" observes="cmd_hline"
+ tooltiptext="&hruleToolbarCmd.tooltip;"/>
+ <toolbarbutton id="tableButton" class="toolbarbutton-1"
+ label="&tableToolbarCmd.label;" observes="cmd_table"
+ tooltiptext="&tableToolbarCmd.tooltip;"/>
+ <toolbarbutton id="linkButton" class="toolbarbutton-1"
+ label="&linkToolbarCmd.label;" observes="cmd_link"
+ tooltiptext="&linkToolbarCmd.tooltip;"/>
+ <toolbarbutton id="namedAnchorButton" class="toolbarbutton-1"
+ label="&anchorToolbarCmd.label;" observes="cmd_anchor"
+ tooltiptext="&anchorToolbarCmd.tooltip;"/>
+
+ <!-- Formatting toolbar items. "value" are HTML tagnames, don't translate -->
+ <menulist class="toolbar-focustarget" id="ParagraphSelect" observes="cmd_renderedHTMLEnabler"
+ tooltiptext="&ParagraphSelect.tooltip;" crop="right">
+ <observes element="cmd_paragraphState" attribute="state" onbroadcast="onParagraphFormatChange(this.parentNode, 'cmd_paragraphState')"/>
+ <menupopup id="ParagraphPopup" oncommand="doStatefulCommand('cmd_paragraphState', event.target.value)">
+ <menuitem label="&bodyTextCmd.label;" value=""/>
+ <menuitem label="¶graphParagraphCmd.label;" value="p"/>
+ <menuitem label="&heading1Cmd.label;" value="h1"/>
+ <menuitem label="&heading2Cmd.label;" value="h2"/>
+ <menuitem label="&heading3Cmd.label;" value="h3"/>
+ <menuitem label="&heading4Cmd.label;" value="h4"/>
+ <menuitem label="&heading5Cmd.label;" value="h5"/>
+ <menuitem label="&heading6Cmd.label;" value="h6"/>
+ <menuitem label="¶graphAddressCmd.label;" value="address"/>
+ <menuitem label="¶graphPreformatCmd.label;" value="pre"/>
+ </menupopup>
+ </menulist>
+
+ <!-- "value" are HTML tagnames, don't translate -->
+ <menulist class="toolbar-focustarget" id="FontFaceSelect" observes="cmd_renderedHTMLEnabler"
+ tooltiptext="&FontFaceSelect.tooltip;" crop="right">
+ <observes element="cmd_fontFace" attribute="state" onbroadcast="onFontFaceChange(this.parentNode, 'cmd_fontFace')"/>
+ <menupopup id="FontFacePopup" oncommand="doStatefulCommand('cmd_fontFace', event.target.value)">
+ <menuitem label="&fontVarWidth.label;" value=""/>
+ <menuitem label="&fontFixedWidth.label;" value="tt"/>
+ <menuseparator/>
+ <menuitem label="&fontHelveticaFont.label;" value="Helvetica, Arial, sans-serif"/>
+ <menuitem label="&fontTimes.label;" value="Times New Roman, Times, serif"/>
+ <menuitem label="&fontCourier.label;" value="Courier New, Courier, monospace"/>
+ <menuseparator/>
+ </menupopup>
+ </menulist>
+
+ <menulist class="toolbar-focustarget" id="FontSizeSelect" oncommand="EditorSelectFontSize()" tooltiptext="&FontSizeSelect.tooltip;" crop="right">
+ <observes element="cmd_fontSize" attribute="state" onbroadcast="onFontSizeChange(this.parentNode, 'cmd_fontSize')"/>
+ <menupopup>
+ <menuitem label="&size-xx-smallCmd.label;"/>
+ <menuitem label="&size-x-smallCmd.label;"/>
+ <menuitem label="&size-smallCmd.label;"/>
+ <menuitem label="&size-mediumCmd.label;"/>
+ <menuitem label="&size-largeCmd.label;"/>
+ <menuitem label="&size-x-largeCmd.label;"/>
+ <menuitem label="&size-xx-largeCmd.label;"/>
+ </menupopup>
+ </menulist>
+
+ <stack id="ColorButtons" align="center">
+ <observes element="cmd_fontColor" attribute="state" onbroadcast="onFontColorChange()"/>
+ <observes element="cmd_backgroundColor" attribute="state" onbroadcast="onBackgroundColorChange()"/>
+ <box class="color-button" id="BackgroundColorButton"
+ onclick="EditorSelectColor('', event);"
+ tooltiptext="&BackgroundColorButton.tooltip;"/>
+ <box class="color-button" id="TextColorButton"
+ onclick="EditorSelectColor('Text', event);"
+ tooltiptext="&TextColorButton.tooltip;"/>
+ </stack>
+ <toolbarbutton id="HighlightColorButton"
+ tooltiptext="&HighlightColorButton.tooltip;" command="cmd_highlight">
+ <observes element="cmd_highlight" attribute="state" onbroadcast="onHighlightColorChange()"/>
+ <observes element="cmd_highlight" attribute="collapsed"/>
+ </toolbarbutton>
+
+<!-- A BUG IN CSS/BOXES MAKES THIS ASSERT WHEN CLASS= IS PRESENT AND WE TRY TO COLLAPSE THE TOOLBOX -->
+ <toolbarbutton id="DecreaseFontSizeButton" observes="cmd_decreaseFont"
+ tooltiptext="&decreaseFontSizeToolbarCmd.tooltip;"/>
+ <toolbarbutton id="IncreaseFontSizeButton" observes="cmd_increaseFont"
+ tooltiptext="&increaseFontSizeToolbarCmd.tooltip;"/>
+
+ <toolbarbutton id="boldButton" type="checkbox" autoCheck="false" observes="cmd_bold"
+ tooltiptext="&boldToolbarCmd.tooltip;">
+ <observes element="cmd_bold" type="checkbox" attribute="state" onbroadcast="onButtonUpdate(this.parentNode, 'cmd_bold')"/>
+ </toolbarbutton>
+ <toolbarbutton id="italicButton" type="checkbox" autoCheck="false" observes="cmd_italic"
+ tooltiptext="&italicToolbarCmd.tooltip;">
+ <observes element="cmd_italic" attribute="state" onbroadcast="onButtonUpdate(this.parentNode, 'cmd_italic')"/>
+ </toolbarbutton>
+ <toolbarbutton id="underlineButton" type="checkbox" autoCheck="false" observes="cmd_underline"
+ tooltiptext="&underlineToolbarCmd.tooltip;">
+ <observes element="cmd_underline" attribute="state" onbroadcast="onButtonUpdate(this.parentNode, 'cmd_underline')"/>
+ </toolbarbutton>
+
+ <toolbarbutton id="ulButton" type="radio" group="lists" autoCheck="false" observes="cmd_ul"
+ tooltiptext="&bulletListToolbarCmd.tooltip;">
+ <observes element="cmd_ul" attribute="state" onbroadcast="onButtonUpdate(this.parentNode, 'cmd_ul')"/>
+ </toolbarbutton>
+
+ <toolbarbutton id="olButton" type="radio" group="lists" autoCheck="false" observes="cmd_ol"
+ tooltiptext="&numberListToolbarCmd.tooltip;">
+ <observes element="cmd_ol" attribute="state" onbroadcast="onButtonUpdate(this.parentNode, 'cmd_ol')"/>
+ </toolbarbutton>
+
+ <toolbarbutton id="outdentButton" observes="cmd_outdent"
+ tooltiptext="&outdentToolbarCmd.tooltip;"/>
+ <toolbarbutton id="indentButton" observes="cmd_indent"
+ tooltiptext="&indentToolbarCmd.tooltip;"/>
+
+ <!-- alignment buttons -->
+ <toolbarbutton id="align-left-button" type="radio" group="align" autoCheck="false"
+ oncommand="doStatefulCommand('cmd_align', 'left')"
+ tooltiptext="&alignLeft.tooltip;" >
+ <observes element="cmd_align" attribute="state"
+ onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_align', 'left')" />
+ </toolbarbutton>
+ <toolbarbutton id="align-center-button" type="radio" group="align" autoCheck="false"
+ oncommand="doStatefulCommand('cmd_align', 'center')"
+ tooltiptext="&alignCenter.tooltip;" >
+ <observes element="cmd_align" attribute="state"
+ onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_align', 'center')"/>
+ </toolbarbutton>
+ <toolbarbutton id="align-right-button" type="radio" group="align" autoCheck="false"
+ oncommand="doStatefulCommand('cmd_align', 'right')"
+ tooltiptext="&alignRight.tooltip;" >
+ <observes element="cmd_align" attribute="state"
+ onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_align', 'right')"/>
+ </toolbarbutton>
+ <toolbarbutton id="align-justify-button" type="radio" group="align" autoCheck="false"
+ oncommand="doStatefulCommand('cmd_align', 'justify')"
+ tooltiptext="&alignJustify.tooltip;" >
+ <observes element="cmd_align" attribute="state"
+ onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_align', 'justify')"/>
+ </toolbarbutton>
+
+ <toolbarbutton id="absolutePositionButton" type="checkbox" tooltiptext="&layer.tooltip;" observes="cmd_absPos">
+ <observes element="cmd_absPos" attribute="state" onbroadcast="onStateButtonUpdate(this.parentNode, 'cmd_absPos', 'absolute')"/>
+ </toolbarbutton>
+ <toolbarbutton id="decreaseZIndexButton" observes="cmd_decreaseZIndex"
+ tooltiptext="&layerSendToBack.tooltip;"/>
+ <toolbarbutton id="increaseZIndexButton" observes="cmd_increaseZIndex"
+ tooltiptext="&layerBringToFront.tooltip;"/>
+
+ <!-- Edit Mode toolbar -->
+ <tabs id="EditModeTabs" onselect="this.selectedItem.doCommand()"/>
+ <tab id="NormalModeButton" class="tab-bottom edit-mode _plain" type="text" selected="1" label="&NormalModeTab.label;" oncommand="goDoCommand('cmd_NormalMode');"
+ tooltiptext="&NormalMode.tooltip;"/>
+ <tab id="TagModeButton" class="tab-bottom edit-mode _plain" type="text" selected="0" label="&AllTagsMode.label;" oncommand="goDoCommand('cmd_AllTagsMode');"
+ tooltiptext="&AllTagsMode.tooltip;"/>
+ <tab id="SourceModeButton" class="tab-bottom edit-mode _plain" type="text" selected="0" label="&SourceMode.label;" oncommand="goDoCommand('cmd_HTMLSourceMode');"
+ tooltiptext="&HTMLSourceMode.tooltip;" dir="&SourceTabDirection;"/>
+ <tab id="PreviewModeButton" class="tab-bottom edit-mode _plain" type="text" selected="0" label="&PreviewMode.label;" oncommand="goDoCommand('cmd_PreviewMode');"
+ tooltiptext="&PreviewMode.tooltip;"/>
+
+ <!-- Paste as quotation is used by mail compose,
+ but in composer it has to go in the debug menu
+ -->
+ <menuitem id="menu_pasteQuote" accesskey="&editpastequotation.accesskey;" command="cmd_pasteQuote" key="pastequotationkb"/>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorPrefsOverlay.xul
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay [
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+%brandDTD;
+<!ENTITY % editorPrefsOverlayDTD SYSTEM "chrome://editor/locale/editorPrefsOverlay.dtd" >
+%editorPrefsOverlayDTD;
+]>
+
+<overlay id="editorPrefsOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <preferences id="appearance_preferences">
+ <preference id="general.startup.editor"
+ name="general.startup.editor"
+ type="bool"/>
+ </preferences>
+
+ <!-- editor startup toggle -->
+ <groupbox id="generalStartupPreferences">
+ <checkbox id="generalStartupEditor"
+ insertafter="generalStartupMail,generalStartupBrowser"
+ label="&editorCheck.label;"
+ accesskey="&editorCheck.accesskey;"
+ preference="general.startup.editor"/>
+ </groupbox>
+ <!-- category tree entries for editor -->
+ <treechildren id="prefsPanelChildren">
+ <treeitem container="true"
+ id="composerItem"
+ insertafter="mailnews,navigator"
+ label="&compose.label;"
+ prefpane="composer_pane"
+ url="chrome://editor/content/pref-composer.xul"
+ helpTopic="composer_prefs_general">
+ <treechildren id="composerChildren">
+ <treeitem id="editingItem"
+ label="&editing.label;"
+ prefpane="editing_pane"
+ url="chrome://editor/content/pref-editing.xul"
+ helpTopic="composer_prefs_newpage"/>
+ <treeitem id="toolbarsItem"
+ label="&toolbars.label;"
+ prefpane="toolbars_pane"
+ url="chrome://editor/content/pref-toolbars.xul"
+ helpTopic="composer_prefs_toolbars"/>
+ </treechildren>
+ </treeitem>
+ </treechildren>
+
+ <!-- category tree entries for editor -->
+ <treechildren id="panelChildren">
+ <treeitem container="true" id="editor" insertafter="mailnews,navigator">
+ <treerow>
+ <treecell label="Migrated: &compose.label;"/>
+ </treerow>
+ <treechildren>
+ <treeitem>
+ <treerow>
+ <treecell label="Migrated: &editing.label;"/>
+ </treerow>
+ </treeitem>
+ <treeitem>
+ <treerow>
+ <treecell label="Migrated: &toolbars.label;"/>
+ </treerow>
+ </treeitem>
+ </treechildren>
+ </treeitem>
+ </treechildren>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorSmileyOverlay.xul
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Smiley Overlay.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/editorSmileyOverlay.dtd">
+
+<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <!-- smiley menu -->
+ <toolbarbutton type="menu" id="smileButtonMenu"
+ observes="cmd_smiley"
+ tooltiptext="&SmileButton.tooltip;">
+ <menupopup id="smilyPopup">
+ <menuitem class="smiley insert-smile menuitem-iconic" label="&smiley1Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-)' )"
+ tooltiptext="&smiley1Cmd.tooltip;" />
+ <menuitem class="smiley insert-frown menuitem-iconic" label="&smiley2Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-(' )"
+ tooltiptext="&smiley2Cmd.tooltip;" />
+ <menuitem class="smiley insert-wink menuitem-iconic" label="&smiley3Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ';-)' )"
+ tooltiptext="&smiley3Cmd.tooltip;" />
+ <menuitem class="smiley insert-tongue menuitem-iconic" label="&smiley4Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-P' )"
+ tooltiptext="&smiley4Cmd.tooltip;" />
+ <menuitem class="smiley insert-laughing menuitem-iconic" label="&smiley5Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-D' )"
+ tooltiptext="&smiley5Cmd.tooltip;" />
+ <menuitem class="smiley insert-embarrassed menuitem-iconic" label="&smiley6Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-[' )"
+ tooltiptext="&smiley6Cmd.tooltip;" />
+ <menuitem class="smiley insert-undecided menuitem-iconic" label="&smiley7Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-\\' )"
+ tooltiptext="&smiley7Cmd.tooltip;" />
+ <menuitem class="smiley insert-surprise menuitem-iconic" label="&smiley8Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '=-O' )"
+ tooltiptext="&smiley8Cmd.tooltip;" />
+ <menuitem class="smiley insert-kiss menuitem-iconic" label="&smiley9Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-*' )"
+ tooltiptext="&smiley9Cmd.tooltip;" />
+ <menuitem class="smiley insert-yell menuitem-iconic" label="&smiley10Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '>:o' )"
+ tooltiptext="&smiley10Cmd.tooltip;" />
+ <menuitem class="smiley insert-cool menuitem-iconic" label="&smiley11Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '8-)' )"
+ tooltiptext="&smiley11Cmd.tooltip;" />
+ <menuitem class="smiley insert-money menuitem-iconic" label="&smiley12Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-$' )"
+ tooltiptext="&smiley12Cmd.tooltip;" />
+ <menuitem class="smiley insert-foot menuitem-iconic" label="&smiley13Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-!' )"
+ tooltiptext="&smiley13Cmd.tooltip;" />
+ <menuitem class="smiley insert-innocent menuitem-iconic" label="&smiley14Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', 'O:-)' )"
+ tooltiptext="&smiley14Cmd.tooltip;" />
+ <menuitem class="smiley insert-cry menuitem-iconic" label="&smiley15Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':\'(' )"
+ tooltiptext="&smiley15Cmd.tooltip;" />
+ <menuitem class="smiley insert-sealed menuitem-iconic" label="&smiley16Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-X' )"
+ tooltiptext="&smiley16Cmd.tooltip;" />
+
+ </menupopup>
+ </toolbarbutton>
+
+ <menu id="insertMenu">
+ <menupopup id="insertMenuPopup">
+ <menu id="insertSmiley" label="&insertSmiley.label;" accesskey="&insertSmiley.accesskey;" insertbefore="insertMenuSeparator">
+ <menupopup id="smilyPopup">
+ <menuitem class="smiley insert-smile menuitem-iconic" label="&smiley1Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-)' )" accesskey="&smiley1Cmd.accesskey;"/>
+ <menuitem class="smiley insert-frown menuitem-iconic" label="&smiley2Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-(' )" accesskey="&smiley2Cmd.accesskey;"/>
+ <menuitem class="smiley insert-wink menuitem-iconic" label="&smiley3Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ';-)' )" accesskey="&smiley3Cmd.accesskey;"/>
+ <menuitem class="smiley insert-tongue menuitem-iconic" label="&smiley4Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-P' )" accesskey="&smiley4Cmd.accesskey;"/>
+ <menuitem class="smiley insert-laughing menuitem-iconic" label="&smiley5Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-D' )" accesskey="&smiley5Cmd.accesskey;"/>
+ <menuitem class="smiley insert-embarrassed menuitem-iconic" label="&smiley6Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-[' )" accesskey="&smiley6Cmd.accesskey;"/>
+ <menuitem class="smiley insert-undecided menuitem-iconic" label="&smiley7Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-\\' )" accesskey="&smiley7Cmd.accesskey;"/>
+ <menuitem class="smiley insert-surprise menuitem-iconic" label="&smiley8Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '=-O' )" accesskey="&smiley8Cmd.accesskey;"/>
+ <menuitem class="smiley insert-kiss menuitem-iconic" label="&smiley9Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-*' )" accesskey="&smiley9Cmd.accesskey;"/>
+ <menuitem class="smiley insert-yell menuitem-iconic" label="&smiley10Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '>:o' )" accesskey="&smiley10Cmd.accesskey;"/>
+ <menuitem class="smiley insert-cool menuitem-iconic" label="&smiley11Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', '8-)' )" accesskey="&smiley11Cmd.accesskey;"/>
+ <menuitem class="smiley insert-money menuitem-iconic" label="&smiley12Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-$' )" accesskey="&smiley12Cmd.accesskey;"/>
+ <menuitem class="smiley insert-foot menuitem-iconic" label="&smiley13Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-!' )" accesskey="&smiley13Cmd.accesskey;"/>
+ <menuitem class="smiley insert-innocent menuitem-iconic" label="&smiley14Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', 'O:-)' )" accesskey="&smiley14Cmd.accesskey;"/>
+ <menuitem class="smiley insert-cry menuitem-iconic" label="&smiley15Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':\'(' )" accesskey="&smiley15Cmd.accesskey;"/>
+ <menuitem class="smiley insert-sealed menuitem-iconic" label="&smiley16Cmd.label;"
+ oncommand="doStatefulCommand('cmd_smiley', ':-X' )" accesskey="&smiley16Cmd.accesskey;"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+ </menu>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorTasksOverlay.xul
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Tasks Overlay.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/tasksOverlay.dtd">
+
+<overlay id="editorTasksOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript">
+ <![CDATA[
+ function toEditor()
+ {
+ if (!CycleWindow("composer:html"))
+ NewEditorWindow();
+ }
+ function NewEditorWindow()
+ {
+ // Open editor window with blank page
+ window.openDialog( "chrome://editor/content", "_blank", "chrome,all,dialog=no", "about:blank");
+ }
+ ]]>
+ </script>
+
+ <keyset id="tasksKeys">
+ <key id="key_editor" key="&editorCmd.commandkey;" command="Tasks:Editor" modifiers="accel"/>
+ </keyset>
+
+ <commandset id="tasksCommands">
+ <command id="Tasks:Editor" oncommand="toEditor();"/>
+ </commandset>
+
+ <statusbarpanel id="component-bar">
+ <toolbarbutton class="taskbutton" id="mini-comp" command="Tasks:Editor"
+ tooltiptext="&taskComposer.tooltip;" insertafter="mini-nav"/>
+ </statusbarpanel>
+
+ <menupopup id="windowPopup">
+ <menuitem label="&editorCmd.label;" accesskey="&editorCmd.accesskey;" key="key_editor" command="Tasks:Editor" id="tasksMenuEditor" insertafter="IMMenuItem,tasksMenuNavigator" class="menuitem-iconic icon-composer16 menu-iconic"/>
+ </menupopup>
+
+</overlay>
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/editorUtilities.js
@@ -0,0 +1,1106 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pete Collins
+ * Brian King
+ * Daniel Glazman <glazman@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**** NAMESPACES ****/
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+// Each editor window must include this file
+// Variables shared by all dialogs:
+
+// Object to attach commonly-used widgets (all dialogs should use this)
+var gDialog = {};
+
+const kOutputEncodeBasicEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeBasicEntities;
+const kOutputEncodeHTMLEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeHTMLEntities;
+const kOutputEncodeLatin1Entities = Components.interfaces.nsIDocumentEncoder.OutputEncodeLatin1Entities;
+const kOutputEncodeW3CEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeW3CEntities;
+const kOutputFormatted = Components.interfaces.nsIDocumentEncoder.OutputFormatted;
+const kOutputLFLineBreak = Components.interfaces.nsIDocumentEncoder.OutputLFLineBreak;
+const kOutputSelectionOnly = Components.interfaces.nsIDocumentEncoder.OutputSelectionOnly;
+const kOutputWrap = Components.interfaces.nsIDocumentEncoder.OutputWrap;
+
+var gStringBundle;
+var gIOService;
+var gPrefsService;
+var gPrefsBranch;
+var gFilePickerDirectory;
+
+var gOS = "";
+const gWin = "Win";
+const gUNIX = "UNIX";
+const gMac = "Mac";
+
+const kWebComposerWindowID = "editorWindow";
+const kMailComposerWindowID = "msgcomposeWindow";
+
+var gIsHTMLEditor;
+/************* Message dialogs ***************/
+
+function AlertWithTitle(title, message, parentWindow)
+{
+ if (!parentWindow)
+ parentWindow = window;
+
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
+ promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
+
+ if (promptService)
+ {
+ if (!title)
+ title = GetString("Alert");
+
+ // "window" is the calling dialog window
+ promptService.alert(parentWindow, title, message);
+ }
+}
+
+// Optional: Caller may supply text to substitue for "Ok" and/or "Cancel"
+function ConfirmWithTitle(title, message, okButtonText, cancelButtonText)
+{
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
+ promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
+
+ if (promptService)
+ {
+ var okFlag = okButtonText ? promptService.BUTTON_TITLE_IS_STRING : promptService.BUTTON_TITLE_OK;
+ var cancelFlag = cancelButtonText ? promptService.BUTTON_TITLE_IS_STRING : promptService.BUTTON_TITLE_CANCEL;
+
+ return promptService.confirmEx(window, title, message,
+ (okFlag * promptService.BUTTON_POS_0) +
+ (cancelFlag * promptService.BUTTON_POS_1),
+ okButtonText, cancelButtonText, null, null, {value:0}) == 0;
+ }
+ return false;
+}
+
+/************* String Utilities ***************/
+
+function GetString(name)
+{
+ if (!gStringBundle)
+ {
+ try {
+ var strBundleService =
+ Components.classes["@mozilla.org/intl/stringbundle;1"].getService();
+ strBundleService =
+ strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
+
+ gStringBundle = strBundleService.createBundle("chrome://editor/locale/editor.properties");
+
+ } catch (ex) {}
+ }
+ if (gStringBundle)
+ {
+ try {
+ return gStringBundle.GetStringFromName(name);
+ } catch (e) {}
+ }
+ return null;
+}
+
+function TrimStringLeft(string)
+{
+ if(!string) return "";
+ return string.replace(/^\s+/, "");
+}
+
+function TrimStringRight(string)
+{
+ if (!string) return "";
+ return string.replace(/\s+$/, '');
+}
+
+// Remove whitespace from both ends of a string
+function TrimString(string)
+{
+ if (!string) return "";
+ return string.replace(/(^\s+)|(\s+$)/g, '')
+}
+
+function IsWhitespace(string)
+{
+ return /^\s/.test(string);
+}
+
+function TruncateStringAtWordEnd(string, maxLength, addEllipses)
+{
+ // Return empty if string is null, undefined, or the empty string
+ if (!string)
+ return "";
+
+ // We assume they probably don't want whitespace at the beginning
+ string = string.replace(/^\s+/, '');
+ if (string.length <= maxLength)
+ return string;
+
+ // We need to truncate the string to maxLength or fewer chars
+ if (addEllipses)
+ maxLength -= 3;
+ string = string.replace(RegExp("(.{0," + maxLength + "})\\s.*"), "$1")
+
+ if (string.length > maxLength)
+ string = string.slice(0, maxLength);
+
+ if (addEllipses)
+ string += "...";
+ return string;
+}
+
+// Replace all whitespace characters with supplied character
+// E.g.: Use charReplace = " ", to "unwrap" the string by removing line-end chars
+// Use charReplace = "_" when you don't want spaces (like in a URL)
+function ReplaceWhitespace(string, charReplace)
+{
+ return string.replace(/(^\s+)|(\s+$)/g,'').replace(/\s+/g,charReplace)
+}
+
+// Replace whitespace with "_" and allow only HTML CDATA
+// characters: "a"-"z","A"-"Z","0"-"9", "_", ":", "-", ".",
+// and characters above ASCII 127
+function ConvertToCDATAString(string)
+{
+ return string.replace(/\s+/g,"_").replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g,'');
+}
+
+function GetSelectionAsText()
+{
+ try {
+ return GetCurrentEditor().outputToString("text/plain", kOutputSelectionOnly);
+ } catch (e) {}
+
+ return "";
+}
+
+
+/************* Get Current Editor and associated interfaces or info ***************/
+const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
+const nsIHTMLEditor = Components.interfaces.nsIHTMLEditor;
+const nsITableEditor = Components.interfaces.nsITableEditor;
+const nsIEditorStyleSheets = Components.interfaces.nsIEditorStyleSheets;
+const nsIEditingSession = Components.interfaces.nsIEditingSession;
+
+function GetCurrentEditor()
+{
+ // Get the active editor from the <editor> tag
+ // XXX This will probably change if we support > 1 editor in main Composer window
+ // (e.g. a plaintext editor for HTMLSource)
+
+ // For dialogs: Search up parent chain to find top window with editor
+ var editor;
+ try {
+ var editorElement = GetCurrentEditorElement();
+ editor = editorElement.getEditor(editorElement.contentWindow);
+
+ // Do QIs now so editor users won't have to figure out which interface to use
+ // Using "instanceof" does the QI for us.
+ editor instanceof Components.interfaces.nsIPlaintextEditor;
+ editor instanceof Components.interfaces.nsIHTMLEditor;
+ } catch (e) { dump (e)+"\n"; }
+
+ return editor;
+}
+
+function GetCurrentTableEditor()
+{
+ var editor = GetCurrentEditor();
+ return (editor && (editor instanceof nsITableEditor)) ? editor : null;
+}
+
+function GetCurrentEditorElement()
+{
+ var tmpWindow = window;
+
+ do {
+ // Get the <editor> element(s)
+ var editorList = tmpWindow.document.getElementsByTagName("editor");
+
+ // This will change if we support > 1 editor element
+ if (editorList.item(0))
+ return editorList.item(0);
+
+ tmpWindow = tmpWindow.opener;
+ }
+ while (tmpWindow);
+
+ return null;
+}
+
+function GetCurrentCommandManager()
+{
+ try {
+ return GetCurrentEditorElement().commandManager;
+ } catch (e) { dump (e)+"\n"; }
+
+ return null;
+}
+
+function GetCurrentEditorType()
+{
+ try {
+ return GetCurrentEditorElement().editortype;
+ } catch (e) { dump (e)+"\n"; }
+
+ return "";
+}
+
+function IsHTMLEditor()
+{
+ // We don't have an editorElement, just return false
+ if (!GetCurrentEditorElement())
+ return false;
+
+ var editortype = GetCurrentEditorType();
+ switch (editortype)
+ {
+ case "html":
+ case "htmlmail":
+ return true;
+
+ case "text":
+ case "textmail":
+ return false
+
+ default:
+ dump("INVALID EDITOR TYPE: " + editortype + "\n");
+ break;
+ }
+ return false;
+}
+
+function PageIsEmptyAndUntouched()
+{
+ return IsDocumentEmpty() && !IsDocumentModified() && !IsHTMLSourceChanged();
+}
+
+function IsInHTMLSourceMode()
+{
+ return (gEditorDisplayMode == kDisplayModeSource);
+}
+
+// are we editing HTML (i.e. neither in HTML source mode, nor editing a text file)
+function IsEditingRenderedHTML()
+{
+ return IsHTMLEditor() && !IsInHTMLSourceMode();
+}
+
+function IsWebComposer()
+{
+ return document.documentElement.id == "editorWindow";
+}
+
+function IsDocumentEditable()
+{
+ try {
+ return GetCurrentEditor().isDocumentEditable;
+ } catch (e) {}
+ return false;
+}
+
+function IsDocumentEmpty()
+{
+ try {
+ return GetCurrentEditor().documentIsEmpty;
+ } catch (e) {}
+ return false;
+}
+
+function IsDocumentModified()
+{
+ try {
+ return GetCurrentEditor().documentModified;
+ } catch (e) {}
+ return false;
+}
+
+function IsHTMLSourceChanged()
+{
+ return gSourceTextEditor.documentModified;
+}
+
+function newCommandParams()
+{
+ try {
+ return Components.classes["@mozilla.org/embedcomp/command-params;1"].createInstance(Components.interfaces.nsICommandParams);
+ }
+ catch(e) { dump("error thrown in newCommandParams: "+e+"\n"); }
+ return null;
+}
+
+/************* General editing command utilities ***************/
+
+function GetDocumentTitle()
+{
+ try {
+ return new XPCNativeWrapper(GetCurrentEditor().document, "title").title;
+ } catch (e) {}
+
+ return "";
+}
+
+function SetDocumentTitle(title)
+{
+
+ try {
+ GetCurrentEditor().setDocumentTitle(title);
+
+ // Update window title (doesn't work if called from a dialog)
+ if ("UpdateWindowTitle" in window)
+ window.UpdateWindowTitle();
+ } catch (e) {}
+}
+
+var gAtomService;
+function GetAtomService()
+{
+ gAtomService = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService);
+}
+
+function EditorGetTextProperty(property, attribute, value, firstHas, anyHas, allHas)
+{
+ try {
+ if (!gAtomService) GetAtomService();
+ var propAtom = gAtomService.getAtom(property);
+
+ GetCurrentEditor().getInlineProperty(propAtom, attribute, value,
+ firstHas, anyHas, allHas);
+ }
+ catch(e) {}
+}
+
+function EditorSetTextProperty(property, attribute, value)
+{
+ try {
+ if (!gAtomService) GetAtomService();
+ var propAtom = gAtomService.getAtom(property);
+
+ GetCurrentEditor().setInlineProperty(propAtom, attribute, value);
+ if ("gContentWindow" in window)
+ window.gContentWindow.focus();
+ }
+ catch(e) {}
+}
+
+function EditorRemoveTextProperty(property, attribute)
+{
+ try {
+ if (!gAtomService) GetAtomService();
+ var propAtom = gAtomService.getAtom(property);
+
+ GetCurrentEditor().removeInlineProperty(propAtom, attribute);
+ if ("gContentWindow" in window)
+ window.gContentWindow.focus();
+ }
+ catch(e) {}
+}
+
+/************* Element enbabling/disabling ***************/
+
+// this function takes an elementID and a flag
+// if the element can be found by ID, then it is either enabled (by removing "disabled" attr)
+// or disabled (setAttribute) as specified in the "doEnable" parameter
+function SetElementEnabledById(elementID, doEnable)
+{
+ SetElementEnabled(document.getElementById(elementID), doEnable);
+}
+
+function SetElementEnabled(element, doEnable)
+{
+ if ( element )
+ {
+ if ( doEnable )
+ element.removeAttribute("disabled");
+ else
+ element.setAttribute("disabled", "true");
+ }
+ else
+ {
+ dump("Element not found in SetElementEnabled\n");
+ }
+}
+
+/************* Services / Prefs ***************/
+
+function GetIOService()
+{
+ if (gIOService)
+ return gIOService;
+
+ gIOService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+
+ return gIOService;
+}
+
+function GetFileProtocolHandler()
+{
+ var ios = GetIOService();
+ var handler = ios.getProtocolHandler("file");
+ return handler.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
+}
+
+function GetPrefsService()
+{
+ if (gPrefsService)
+ return gPrefsService;
+
+ try {
+ gPrefsService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+ }
+ catch(ex) {
+ dump("failed to get prefs service!\n");
+ }
+
+ return gPrefsService;
+}
+
+function GetPrefs()
+{
+ if (gPrefsBranch)
+ return gPrefsBranch;
+
+ try {
+ var prefService = GetPrefsService();
+ if (prefService)
+ gPrefsBranch = prefService.getBranch(null);
+
+ if (gPrefsBranch)
+ return gPrefsBranch;
+ else
+ dump("failed to get root prefs!\n");
+ }
+ catch(ex) {
+ dump("failed to get root prefs!\n");
+ }
+ return null;
+}
+
+function GetStringPref(name)
+{
+ try {
+ return GetPrefs().getComplexValue(name, Components.interfaces.nsISupportsString).data;
+ } catch (e) {}
+ return "";
+}
+
+function GetBoolPref(name)
+{
+ try {
+ return GetPrefs().getBoolPref(name);
+ } catch (e) {}
+ return false;
+}
+
+function SetUnicharPref(aPrefName, aPrefValue)
+{
+ var prefs = GetPrefs();
+ if (prefs)
+ {
+ try {
+ var str = Components.classes["@mozilla.org/supports-string;1"]
+ .createInstance(Components.interfaces.nsISupportsString);
+ str.data = aPrefValue;
+ prefs.setComplexValue(aPrefName, Components.interfaces.nsISupportsString, str);
+ }
+ catch(e) {}
+ }
+}
+
+function GetUnicharPref(aPrefName, aDefVal)
+{
+ var prefs = GetPrefs();
+ if (prefs)
+ {
+ try {
+ return prefs.getComplexValue(aPrefName, Components.interfaces.nsISupportsString).data;
+ }
+ catch(e) {}
+ }
+ return "";
+}
+
+// Set initial directory for a filepicker from URLs saved in prefs
+function SetFilePickerDirectory(filePicker, fileType)
+{
+ if (filePicker)
+ {
+ try {
+ var prefBranch = GetPrefs();
+ if (prefBranch)
+ {
+ // Save current directory so we can reset it in SaveFilePickerDirectory
+ gFilePickerDirectory = filePicker.displayDirectory;
+
+ var location = prefBranch.getComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile);
+ if (location)
+ filePicker.displayDirectory = location;
+ }
+ }
+ catch(e) {}
+ }
+}
+
+// Save the directory of the selected file to prefs
+function SaveFilePickerDirectory(filePicker, fileType)
+{
+ if (filePicker && filePicker.file)
+ {
+ try {
+ var prefBranch = GetPrefs();
+
+ var fileDir;
+ if (filePicker.file.parent)
+ fileDir = filePicker.file.parent.QueryInterface(Components.interfaces.nsILocalFile);
+
+ if (prefBranch)
+ prefBranch.setComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile, fileDir);
+
+ var prefsService = GetPrefsService();
+ prefsService.savePrefFile(null);
+ } catch (e) {}
+ }
+
+ // Restore the directory used before SetFilePickerDirectory was called;
+ // This reduces interference with Browser and other module directory defaults
+ if (gFilePickerDirectory)
+ filePicker.displayDirectory = gFilePickerDirectory;
+
+ gFilePickerDirectory = null;
+}
+
+function GetDefaultBrowserColors()
+{
+ var prefs = GetPrefs();
+ var colors = { TextColor:0, BackgroundColor:0, LinkColor:0, ActiveLinkColor:0 , VisitedLinkColor:0 };
+ var useSysColors = false;
+ try { useSysColors = prefs.getBoolPref("browser.display.use_system_colors"); } catch (e) {}
+
+ if (!useSysColors)
+ {
+ try { colors.TextColor = prefs.getCharPref("browser.display.foreground_color"); } catch (e) {}
+
+ try { colors.BackgroundColor = prefs.getCharPref("browser.display.background_color"); } catch (e) {}
+ }
+ // Use OS colors for text and background if explicitly asked or pref is not set
+ if (!colors.TextColor)
+ colors.TextColor = "windowtext";
+
+ if (!colors.BackgroundColor)
+ colors.BackgroundColor = "window";
+
+ colors.LinkColor = prefs.getCharPref("browser.anchor_color");
+ colors.ActiveLinkColor = prefs.getCharPref("browser.active_color");
+ colors.VisitedLinkColor = prefs.getCharPref("browser.visited_color");
+
+ return colors;
+}
+
+/************* URL handling ***************/
+
+function TextIsURI(selectedText)
+{
+ return selectedText && /^http:\/\/|^https:\/\/|^file:\/\/|\
+ ^ftp:\/\/|^about:|^mailto:|^news:|^snews:|^telnet:|^ldap:|\
+ ^ldaps:|^gopher:|^finger:|^javascript:/i.test(selectedText);
+}
+
+function IsUrlAboutBlank(urlString)
+{
+ return (urlString == "about:blank");
+}
+
+function MakeRelativeUrl(url)
+{
+ var inputUrl = TrimString(url);
+ if (!inputUrl)
+ return inputUrl;
+
+ // Get the filespec relative to current document's location
+ // NOTE: Can't do this if file isn't saved yet!
+ var docUrl = GetDocumentBaseUrl();
+ var docScheme = GetScheme(docUrl);
+
+ // Can't relativize if no doc scheme (page hasn't been saved)
+ if (!docScheme)
+ return inputUrl;
+
+ var urlScheme = GetScheme(inputUrl);
+
+ // Do nothing if not the same scheme or url is already relativized
+ if (docScheme != urlScheme)
+ return inputUrl;
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return inputUrl;
+
+ // Host must be the same
+ var docHost = GetHost(docUrl);
+ var urlHost = GetHost(inputUrl);
+ if (docHost != urlHost)
+ return inputUrl;
+
+
+ // Get just the file path part of the urls
+ // XXX Should we use GetCurrentEditor().documentCharacterSet for 2nd param ?
+ var docPath = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null).path;
+ var urlPath = IOService.newURI(inputUrl, GetCurrentEditor().documentCharacterSet, null).path;
+
+ // We only return "urlPath", so we can convert
+ // the entire docPath for case-insensitive comparisons
+ var os = GetOS();
+ var doCaseInsensitive = (docScheme == "file" && os == gWin);
+ if (doCaseInsensitive)
+ docPath = docPath.toLowerCase();
+
+ // Get document filename before we start chopping up the docPath
+ var docFilename = GetFilename(docPath);
+
+ // Both url and doc paths now begin with "/"
+ // Look for shared dirs starting after that
+ urlPath = urlPath.slice(1);
+ docPath = docPath.slice(1);
+
+ var firstDirTest = true;
+ var nextDocSlash = 0;
+ var done = false;
+
+ // Remove all matching subdirs common to both doc and input urls
+ do {
+ nextDocSlash = docPath.indexOf("\/");
+ var nextUrlSlash = urlPath.indexOf("\/");
+
+ if (nextUrlSlash == -1)
+ {
+ // We're done matching and all dirs in url
+ // what's left is the filename
+ done = true;
+
+ // Remove filename for named anchors in the same file
+ if (nextDocSlash == -1 && docFilename)
+ {
+ var anchorIndex = urlPath.indexOf("#");
+ if (anchorIndex > 0)
+ {
+ var urlFilename = doCaseInsensitive ? urlPath.toLowerCase() : urlPath;
+
+ if (urlFilename.indexOf(docFilename) == 0)
+ urlPath = urlPath.slice(anchorIndex);
+ }
+ }
+ }
+ else if (nextDocSlash >= 0)
+ {
+ // Test for matching subdir
+ var docDir = docPath.slice(0, nextDocSlash);
+ var urlDir = urlPath.slice(0, nextUrlSlash);
+ if (doCaseInsensitive)
+ urlDir = urlDir.toLowerCase();
+
+ if (urlDir == docDir)
+ {
+
+ // Remove matching dir+"/" from each path
+ // and continue to next dir
+ docPath = docPath.slice(nextDocSlash+1);
+ urlPath = urlPath.slice(nextUrlSlash+1);
+ }
+ else
+ {
+ // No match, we're done
+ done = true;
+
+ // Be sure we are on the same local drive or volume
+ // (the first "dir" in the path) because we can't
+ // relativize to different drives/volumes.
+ // UNIX doesn't have volumes, so we must not do this else
+ // the first directory will be misinterpreted as a volume name
+ if (firstDirTest && docScheme == "file" && os != gUNIX)
+ return inputUrl;
+ }
+ }
+ else // No more doc dirs left, we're done
+ done = true;
+
+ firstDirTest = false;
+ }
+ while (!done);
+
+ // Add "../" for each dir left in docPath
+ while (nextDocSlash > 0)
+ {
+ urlPath = "../" + urlPath;
+ nextDocSlash = docPath.indexOf("\/", nextDocSlash+1);
+ }
+ return urlPath;
+}
+
+function MakeAbsoluteUrl(url)
+{
+ var resultUrl = TrimString(url);
+ if (!resultUrl)
+ return resultUrl;
+
+ // Check if URL is already absolute, i.e., it has a scheme
+ var urlScheme = GetScheme(resultUrl);
+
+ if (urlScheme)
+ return resultUrl;
+
+ var docUrl = GetDocumentBaseUrl();
+ var docScheme = GetScheme(docUrl);
+
+ // Can't relativize if no doc scheme (page hasn't been saved)
+ if (!docScheme)
+ return resultUrl;
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return resultUrl;
+
+ // Make a URI object to use its "resolve" method
+ var absoluteUrl = resultUrl;
+ var docUri = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null);
+
+ try {
+ absoluteUrl = docUri.resolve(resultUrl);
+ // This is deprecated and buggy!
+ // If used, we must make it a path for the parent directory (remove filename)
+ //absoluteUrl = IOService.resolveRelativePath(resultUrl, docUrl);
+ } catch (e) {}
+
+ return absoluteUrl;
+}
+
+// Get the HREF of the page's <base> tag or the document location
+// returns empty string if no base href and document hasn't been saved yet
+function GetDocumentBaseUrl()
+{
+ try {
+ var docUrl;
+
+ // if document supplies a <base> tag, use that URL instead
+ var baseList = GetCurrentEditor().document.getElementsByTagName("base");
+ if (baseList)
+ {
+ var base = baseList.item(0);
+ if (base)
+ docUrl = base.getAttribute("href");
+ }
+ if (!docUrl)
+ docUrl = GetDocumentUrl();
+
+ if (!IsUrlAboutBlank(docUrl))
+ return docUrl;
+ } catch (e) {}
+ return "";
+}
+
+function GetDocumentUrl()
+{
+ try {
+ var aDOMHTMLDoc = GetCurrentEditor().document.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
+ return aDOMHTMLDoc.URL;
+ }
+ catch (e) {}
+ return "";
+}
+
+// Extract the scheme (e.g., 'file', 'http') from a URL string
+function GetScheme(urlspec)
+{
+ var resultUrl = TrimString(urlspec);
+ // Unsaved document URL has no acceptable scheme yet
+ if (!resultUrl || IsUrlAboutBlank(resultUrl))
+ return "";
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return "";
+
+ var scheme = "";
+ try {
+ // This fails if there's no scheme
+ scheme = IOService.extractScheme(resultUrl);
+ } catch (e) {}
+
+ return scheme ? scheme.toLowerCase() : "";
+}
+
+function GetHost(urlspec)
+{
+ if (!urlspec)
+ return "";
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return "";
+
+ var host = "";
+ try {
+ host = IOService.newURI(urlspec, null, null).host;
+ } catch (e) {}
+
+ return host;
+}
+
+function GetUsername(urlspec)
+{
+ if (!urlspec)
+ return "";
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return "";
+
+ var username = "";
+ try {
+ username = IOService.newURI(urlspec, null, null).username;
+ } catch (e) {}
+
+ return username;
+}
+
+function GetFilename(urlspec)
+{
+ if (!urlspec || IsUrlAboutBlank(urlspec))
+ return "";
+
+ var IOService = GetIOService();
+ if (!IOService)
+ return "";
+
+ var filename;
+
+ try {
+ var uri = IOService.newURI(urlspec, null, null);
+ if (uri)
+ {
+ var url = uri.QueryInterface(Components.interfaces.nsIURL);
+ if (url)
+ filename = url.fileName;
+ }
+ } catch (e) {}
+
+ return filename ? filename : "";
+}
+
+// Return the url without username and password
+// Optional output objects return extracted username and password strings
+// This uses just string routines via nsIIOServices
+function StripUsernamePassword(urlspec, usernameObj, passwordObj)
+{
+ urlspec = TrimString(urlspec);
+ if (!urlspec || IsUrlAboutBlank(urlspec))
+ return urlspec;
+
+ if (usernameObj)
+ usernameObj.value = "";
+ if (passwordObj)
+ passwordObj.value = "";
+
+ // "@" must exist else we will never detect username or password
+ var atIndex = urlspec.indexOf("@");
+ if (atIndex > 0)
+ {
+ try {
+ var IOService = GetIOService();
+ if (!IOService)
+ return urlspec;
+
+ var uri = IOService.newURI(urlspec, null, null);
+ var username = uri.username;
+ var password = uri.password;
+
+ if (usernameObj && username)
+ usernameObj.value = username;
+ if (passwordObj && password)
+ passwordObj.value = password;
+ if (username)
+ {
+ var usernameStart = urlspec.indexOf(username);
+ if (usernameStart != -1)
+ return urlspec.slice(0, usernameStart) + urlspec.slice(atIndex+1);
+ }
+ } catch (e) {}
+ }
+ return urlspec;
+}
+
+function StripPassword(urlspec, passwordObj)
+{
+ urlspec = TrimString(urlspec);
+ if (!urlspec || IsUrlAboutBlank(urlspec))
+ return urlspec;
+
+ if (passwordObj)
+ passwordObj.value = "";
+
+ // "@" must exist else we will never detect password
+ var atIndex = urlspec.indexOf("@");
+ if (atIndex > 0)
+ {
+ try {
+ var IOService = GetIOService();
+ if (!IOService)
+ return urlspec;
+
+ var password = IOService.newURI(urlspec, null, null).password;
+
+ if (passwordObj && password)
+ passwordObj.value = password;
+ if (password)
+ {
+ // Find last ":" before "@"
+ var colon = urlspec.lastIndexOf(":", atIndex);
+ if (colon != -1)
+ {
+ // Include the "@"
+ return urlspec.slice(0, colon) + urlspec.slice(atIndex);
+ }
+ }
+ } catch (e) {}
+ }
+ return urlspec;
+}
+
+// Version to use when you have an nsIURI object
+function StripUsernamePasswordFromURI(uri)
+{
+ var urlspec = "";
+ if (uri)
+ {
+ try {
+ urlspec = uri.spec;
+ var userPass = uri.userPass;
+ if (userPass)
+ {
+ start = urlspec.indexOf(userPass);
+ urlspec = urlspec.slice(0, start) + urlspec.slice(start+userPass.length+1);
+ }
+ } catch (e) {}
+ }
+ return urlspec;
+}
+
+function InsertUsernameIntoUrl(urlspec, username)
+{
+ if (!urlspec || !username)
+ return urlspec;
+
+ try {
+ var ioService = GetIOService();
+ var URI = ioService.newURI(urlspec, GetCurrentEditor().documentCharacterSet, null);
+ URI.username = username;
+ return URI.spec;
+ } catch (e) {}
+
+ return urlspec;
+}
+
+function GetOS()
+{
+ if (gOS)
+ return gOS;
+
+ var platform = navigator.platform.toLowerCase();
+
+ if (platform.indexOf("win") != -1)
+ gOS = gWin;
+ else if (platform.indexOf("mac") != -1)
+ gOS = gMac;
+ else if (platform.indexOf("unix") != -1 || platform.indexOf("linux") != -1 || platform.indexOf("sun") != -1)
+ gOS = gUNIX;
+ else
+ gOS = "";
+ // Add other tests?
+
+ return gOS;
+}
+
+function ConvertRGBColorIntoHEXColor(color)
+{
+ if ( /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.test(color) ) {
+ var r = Number(RegExp.$1).toString(16);
+ if (r.length == 1) r = "0"+r;
+ var g = Number(RegExp.$2).toString(16);
+ if (g.length == 1) g = "0"+g;
+ var b = Number(RegExp.$3).toString(16);
+ if (b.length == 1) b = "0"+b;
+ return "#"+r+g+b;
+ }
+ else
+ {
+ return color;
+ }
+}
+
+/************* CSS ***************/
+
+function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
+{
+ var prefs = GetPrefs();
+ var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
+ var value;
+ if (IsCSSPrefChecked && IsHTMLEditor())
+ value = element.style.getPropertyValue(cssPropertyName);
+
+ if (!value)
+ value = element.getAttribute(attrName);
+
+ if (!value)
+ return "";
+
+ return value;
+}
+
+/************* Miscellaneous ***************/
+// Clone simple JS objects
+function Clone(obj)
+{
+ var clone = {};
+ for (var i in obj)
+ {
+ if( typeof obj[i] == 'object')
+ clone[i] = Clone(obj[i]);
+ else
+ clone[i] = obj[i];
+ }
+ return clone;
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3162d275d5a7eda06c34d2edc7ca9757ff059f32
GIT binary patch
literal 893
zc${<hbhEHb6l4%&_|CvEW$D&y*RK6%VE8`@M#0Dfia%Kx85o!tbQpjDlqVQCq8L~?
zSR4cz4m5M{Gf5mMXgJuyA#RrPLtqg@C#$hokB4Ey@qRh&xHlZ17N3~N;5DnoBOukI
sTQgQD<)zVqLz4|dlX@bGmpk=JYDURe1irX1k=Oswor*6R4h#&|02^i@3;+NC
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..78f142f47f1f33927242a4c884ecf1757f436301
GIT binary patch
literal 145
zc${<hbhEHb6l4%&*vtR|EiEno85sWmfBv5cp!k!8k%57UK?kH0WCjC^U4Vx}<DMT)
z2b#~`xK=2y(GeQe`sBgByvl7Kw9h-_Hcye8Z7JXSTskMuQC2G?CM!g9Ql`-)zx27%
L1*Lo47#OSp?8iyz
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..858bdfd499e479d7ee5963e01ba8c9e12fbea620
GIT binary patch
literal 897
zc${<hbhEHb6l4%&_|CvEW$D&y*RK6%VE8`@M#0Dfia%Kx85o!tbQpjDlqVQC;uu&t
zSR4cz4m5M{GjSX+XgJuyA#RrPLtqg@r!cozkHy4C4gJhoac^D-q<HknGR_dO+_do2
yQ~}dje@+xVI5R<7cpppW#f9gls<^)6ku+I!Y@UcNpU$c+sh5^97qhW2SOWmJWFo)-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a25a2e2e8e9590f8a8c1e9e41f97de252bf79415
GIT binary patch
literal 148
zc${<hbhEHb6l4%&*vtR|EiEno85sWmfBv5cp!k!8k%57UK?kH0WCjC^V}OT4<DMT)
z2b#~`xK=2y(UBb5s%*K(xpJGF%x2w$)5Xi*D@=WRbT&`&>NEUppESx%ZW@X4uAHTE
QdC97`sk<kqurOEy0LRx&TL1t6
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3a63d01d1898c0f5fa9397dd705c6bab9dbfe272
GIT binary patch
literal 138
zc${<hbhEHb6lM@$Sj5io|9=A`BV$5B!h!`08X6o997u3*P&jblfZ|UUMg|6U1|0?<
z0I6kQ_Ltaor%JuSb2YEht=Nwfqyuy0A_UtUx$dV49K5mdS%}9A*Jy(%=B3<;5(;Oc
qL?SkcEfGl(R$h8CQgQXJ{^Z>WvMdiaRPe|-u)Ww))$7N=U=09T-7nz)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e97c5b8008e9664f8ccadc0f95cd48a75ba1a3fd
GIT binary patch
literal 202
zc$@*s05$(dNk%w1VIlw!0HOx~|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui03rYo000Az7`oj4?3@6qy*TR{#@t|Nbp&MzMO6r_ptdfswkbfGfM6Jv5U>V{
z4=DWU0;!wD;7j>>MQ9H9vkgirA#bSL8h2A-@@g6e!^hPZX{M4nEhCjRe*(Z(tUbI|
zi|qwfN(D7NGb|~GC^9iJV^|`Q8A_6s9AprgnhaM51D~LwqNAjt1QG<Ps;jK6uB!<E
EJAcni*8l(j
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0aefc06ff9a874bac8489cc05d199f1cba455528
GIT binary patch
literal 279
zc$@(j0qFimNk%w1VK@K~0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05|{;06+uW7`oj4FvfEN2qNPW3IKwI0i0(TA8=j*skET=VWD;rgDk9{L3bB}
z2E`HjJPHphWD<=+BAhHmty-_xEH)t3dcR;RH|GMOLSkVEHTs}2s}U!FVu{|;g3|pd
zWRwDXFd!Kzfrd(ch#({_V-y6Dl9QB`mY0~9WMQ10Vgwb7DSn598H1*yf_j34fR0@%
zOfG<TZWcT$Y;-d%CnXmOD#BwHH9j#^NJ4FG$r~MQXuS(~In&8L8b~n6MLR%k+P5h`
dHpQOlp2ZUF?(Yvc6a)12_V@Vt`uqC{06PYCZ0Z02
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e3f49a9635ab7a558fda28b1f76a4685750a0606
GIT binary patch
literal 240
zc$@+701y91Nk%w1VGsZ;0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBy06+t^7`n`N0Z3qgnwE?xi}*q@1sVqk7%Gt)=8on2vSwk}H{5oZxW<x?
z;p5BfPCk#0BN(1kzoRT_`b0j<2`UGrX-~myuxZFqF$P6N4Df)8-Z7{P?4$#9X<MN1
zu?_@*f`fy4G9(Z^PZ)7vSa~K$N^BuSkP`&~Hvw>UC@Pm@Ls(~8A|aGWE{$$Plu4ma
qb8Hl9jGifMt*E6gd@6A^cutgeP)3m{ekBdf3K|as($mz`2>?4q5n9mz
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ccb809b50beeac3adadbe3670c3fba9eceb9d3a3
GIT binary patch
literal 127
zc${<hbhEHb6lM@$Sj5V3;6MT+BV$5B!h!`0{{L?{aNs~gg98HtgW^vXMg|5}1|1-q
z0i>3J*+pX4oha1_o~wD4q86EnH-~gS;+Ph)J@H}JvgNNg>WA0Ab(xfw_g^bk=jslg
fPRAMNlX)!XaR)d$tc_ZKg)!y8+p7I{SQxAUi(xMT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4faf7d23a7c38c0500bd5ffa7461a056a720dde
GIT binary patch
literal 230
zc$@*|02%*BNk%w1VJ-j=0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04@L!06+t)7`oj45S|kN2qNPvtQD09de%mAWIzldAQ*-h7;jL38r_z3=FgeZ
zYIiCck4V`t$!sE3EK8yC;?-^#knRKwmO9F4p+M>g$etVN<|F$u=yPgyAlUEtynfH;
zN1cFxDimdCE^Pp8L26}hif}@I06J(USs^$?CMjT%m>32jU2a)snmwJH7fT}_6{@YS
gh+T3hVMKwsMNkpFzP}1|2Lr^##>dFX%E}1<J7)!2T>t<8
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f16f585235922d7bddad19e5703c64cd2c95a0b9
GIT binary patch
literal 212
zc$@*$04x7TNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+to7`oj4@SFfD2qI%afiV?k0fLbkT}TXRRf6P(7MGdPHEsoKJO03+
zkjD}lk3nLqKq<ve0b0N&sF*IgOV3is3JTRqmz24M#X91Fz;3(W@VLB)tRHz3;8$GU
zlgl_@KuSL*Q87DJA|p&rBZL+lB~2J8J5(WtXIgZKE*Kq+HGqp3XOMQOKS~g-t`I8{
O1GBWXwzs&s2>?44l2AMV
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d54916a758cc355a164694068d9d53f506514562
GIT binary patch
literal 138
zc$@)>0CoRINk%w1VG{rl0IC20|Nnpi0Rf<(pkQENfPg^2z`#I2Ai%(2A^8LW000F5
zEC2ui022TZ06+sz7`ohAC4dQtoPkgfhPabO5C({O=BA$C>awOt8fw>4$2cCfR}8?Q
sa0tA;dXY^|x3a}9mY%VaAq998=SEh-!j4UpW4!Pc1n9JSjZOdnJ2ieap8x;=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..de5a77335c1e9d0a789789618537b8acd2b81792
GIT binary patch
literal 216
zc$@*)04M)PNk%w1VGsZ$0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq06+ts7`n`N0RYj0kb#USizpL_X`Ix3X11AZt8&6sfbqCa1`Ze(@Ja&S
zq-TR&YBe9J#Z=yq$KJ2y5jkPG07!Uc6$}dE)Z|f!romv2JN3lgXU%~?uiNdnW{LpO
zv(QmPML>Z`ZEtXc5?}=jdrucahD#U<J0)W*6jGF57F>!rVSkiNC|#9cW{OaPs1yyH
Sd44YywsHppy1Tr*2>?6tEL8OX
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4a8a8d2ef97e543a6051d444f020b6430e767924
GIT binary patch
literal 186
zc$@*c07d^tNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui03HAk06+tO7`oj4=L7)6q(Oj8O937Qej71dmLL>YP^^Ig7%nWAr>O6Ik6*rE
zFJMAtRwPbkqFiE%6oX22n+k4}sg5`}5We8BcudX-&s%~dY86?r6;;}7$+k43d?yKA
os#r2gbxn0Yc7HJ&FMu;OjD~2DTo06$3?>l+nwy-Ro}UQ-J5B#W#Q*>R
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a137f167c66fa450513bdb34e6e77aca45f7fe56
GIT binary patch
literal 176
zc$@*S08jr%Nk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tE7`oj4=LA53m^28WODL6Aam0X8mmnCJ$f|)clICpRcu<~rZ|k*6
zY9-^qd_Z17r2<);OVzJ*AXu;1tacmpc|!!rC@MuknbWQXbIAxi(9bA28nQr|Hb=1m
etL<_wd3SR=Uxzdgii-?X2Lq6il9QB`2>?5uvP6*p
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ae2b791e8d7150f03d0c25d7d55a395a43a4b1be
GIT binary patch
literal 281
zc$@(l0p|WkNk%w1VGsZ;0J{JH|Nnpi0Rf<(pkQENRaGj0fIzCMRX{)>z`$URjz_@2
zz~kd_IXN71aycCx4gdfEA^8LW000UAEC2ui01yBy06+xBFvv-%QUPd?_YQ;5X~Ci;
z1R0Ki;TonYdi1x}H8^i+YNVXoCV|tj2uMNzAsdYfheGoMJpiIpoX5DO0J)zeff(Fr
z7!AOJK?V<z%xn!M2NWhy`N0Z6IE7kr83j^=G71BUii?Y8fgl(jJuP2=0Fys;F*I%*
zF9va)EH;j75@~fKnPn^u3<e1fp_ZSUogQ?ol1WQ-G_z)V8h*e|8wiHF8+QQ*ampM4
fQk;MYQ3uV%A9jV)ZWYo^;Nu||0_W)I=@9@sXlP{|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f91a05df15970b235f820b6bb4dae0a84a666aec
GIT binary patch
literal 214
zc$@*&04e`RNk%w1VGsZ$0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq06+tq7`n`N0RRz-yfTmxvCms46@p-08uxu^R|Lk1wUS_9h5)LQewDip
zaOk70W+BXLQA~~uiWtgiE0uD=3v_YI0$wMu7Z6>XjFd)ma3Hwfa5(P>f{c7D=ND={
z>!Dppb96>8IW`quKtF3j4FQcxB{F1AVqb}sJc~7v5?fJIgLg7$IR-aannF56UL;nN
QL65W>4+FTly1EGfI}JBY!2kdN
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f31b0ceed9bb0f5ea73a9080bc1fad5d02d2d60
GIT binary patch
literal 158
zc$@*A0Ac?}Nk%w1VHN-o0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui02Tlc06+s{7`ohjCjcPi45ChBCJ4k}Rhc1?f>~Ul<-PC=ig69kBbIik%F=*B
zCbJTH3ad}(KxjIjP$<x514SmnA$BN8DuEix$%XmlN&z9pBx_B2>2RU^bx~tDhu*O~
M4E}(Df`SPEJ0HtDHUIzs
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2c7dcac011f9e5f15ad2a75443cf863b01e8eaab
GIT binary patch
literal 264
zc$@(U0r&n#Nk%w1VK@K~0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05|{;06+uH7`oj4FvfEN0K(oN02di(Tpp-h8Hs6zLUO7{3|c6(<UImKVCXB5
z@FOT>b{XRl^qQSw(5Q4uRRx^YtaiJ>27x@wE$l0Pi?&WOU_8OBUL~l&qvudeo^akF
z8U1}2c1;5Z1c!);ii?bmj*c{3l9O;17jl6pgBW?3XhL*>e|u(Kkt--CKWwNQt*I&*
ztSK9rGN(2zp&U4uH*9HbLZ}9-FSb{>AG)+FJwMDuCb1elZpdDg+FHpH-rwL5GZX{m
O=I7|?>g(+62>?5ymTPVR
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b8a0bbb744311ea11f45d2425601cfbdcf198d73
GIT binary patch
literal 247
zc$@+E00{p_Nk%w1VK@K~0IC20|Nnpi0Rh0kz<_{2prD{&U|_(&U_d}1A^8LW00062
zEC2ui05Sj&06+u07`oj4FfJhi7#4sqcE6dYY1nuiCdvVZ@&yH9VZ(4_D`?cgQP;Pc
zq2;?7Hi4sP6AO)=(5Q4uWy-49tQK~q*-*=pCPxa9OPte^YuWvjEa7tik3)YWdS1yD
z6#jsLf`f#GhJaUEii;yK6>)eZN;?-nbZ(KAA1rWsRx=r5Ibus?DW?ixIcy+6NnvK2
xAdQ=7bV;jCtv0V-WMs1%M7&2iL1Vg%%2{j@&d<<&0tD36*4NnC+S}C$06QIWWm^CM
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dcb4229c612a4f096542454f103f1efa56bf5694
GIT binary patch
literal 192
zc$@*i06+gnNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tU7`oj4@SFf@EumCFxedY>S|kt<163Lzr?~=W#O54p<e8Ry@B2E{
zZ%C{JOCF>U^s$X{C?TnEyF3LrKx~^eq7H<xcuX#v&%2@;NSO4fSgUp$r^lgb3kK&&
unx0H-c^gtMOMp&1M=LEET8B+sC5vm7A5jpQnh;+H1D~LwqNAjx2>?4jC`gn5
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2a72bd010cbfdaf54c303482be0c89e7f109f148
GIT binary patch
literal 251
zc$@+I00jR>Nk%w1VKM*^0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui05Sj&06+u47`oj4Fs^d~Fu?#IY$+S?0f7*T;MS2QrmZJQ43=1S8deBJ#-2K!
zFR<%?Is)S+FssF$(5O_(q)o5bY}Eogl|rj;NbD^VIk&USx-ld*;AA{$QoU7h&ZX|1
z9SDGdf`f#GhKGS{S&NKI1Qj7}0(l&Acu#b2be58qYZfjl9w{h4AtM_jVk<B(TWCP0
zuw*|S3M4zLH+-))Nj^b68bov##7bg4ura-j&R1I!($myc6a(1V+S}aS-rv~?06RFL
BVx<58
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f72558c1e5580bcdf60e478c6fa8ca8998044981
GIT binary patch
literal 211
zc$@*#04)DUNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tn7`oj4@SFfZ38e~ZOa&dVRaX`W-xm-ART<}&U4{T>o3MF6Q0ti<
z%atk`kI2fZm25gwOV_A)`i!PMluw6J4pRkSiu(zZHC#b(c_6so@VI<VXFl)9)dVcI
z>dI+;Tx(wz7#bWrARbdCSw>NaV2_emRa<{vb|5i_G&YAhJ4!!lnnZZ1rx2{I5G)b{
Nva__cwzs$m06V)>P@4b%
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f8938feb4c44e6c4550e3d12cec86c770364fea4
GIT binary patch
literal 183
zc$@*Z07(BwNk%w1VIBYw0IC20|Nnpi0Rf<(pkQENfPg^2z+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tL7`oj4=L7&sD3nZNDBwUqcwR6F6J>}RW*Nkai6mvBb*}Gsy8pUf
z##b5*Lq?L&Qy>s99%oYOES(O6tai)odU3$8av&i!pCoA%ItE*ynomd7q1BdgCNes)
lw|y&47Zm|8G9fTkHYY@4Ks^tUk_%S{0+*PXnwy*n06YE6K~4Yw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9ab2bc9de846b9e302828a24c90d5438ac91cda3
GIT binary patch
literal 262
zc$@(S0r~z%Nk%w1VKx8|0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05$*+06+uF7`oj4FurpF040<wtT4joSy$PamSL1C5D1t8yTm{O#@lUIVDO!g
zFO&-vP8m>cqu{-IwOeUQty-^GY9N~JdcV`HjU#2jG=N}dmA;*xWY=c}7fX)<;IzP>
z?fpk4AtpR&PBjMvii?bmj*pO$k7Hn!mSF@He|di;c!Qsyej$K`oHUdfKqMI-ac!@#
zEf*~cY;|0)o;@H>YNKuzaIi0`xRf|LXv4}?Cviz4OfyAL$d}k&b`sp(-VKNc1LNf7
M=I7|?>gWjoJCZGJKL7v#
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b6ec228da1105b5b3a851dac6f05dff93d8947da
GIT binary patch
literal 229
zc$@*{02=>CNk%w1VGsZ;0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBy06+t(7`n`N0mw;ZAS2p3Z>B;ZRGtP1Xj)j9$#rd46w1hc8+zL1OU9eR
zNC)U`CPbs}X41Hdz~XKS#VxB%pE4B+tguL~;H!-2lF@=;B!XFKC_@u-AlUDCymfhj
zAQdxhU`JjQWeq%0HY+ns9aCsl4T5D_QIm<1mR4e8judJJUxNU0Ybaz<e3y`!O#%jM
fYoAw2u@W??lB2Vv0767elf!fe1INh8$q4{EfACn0
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dd15a3d5ae8098fd436da0aa82af620b2f5a155f
GIT binary patch
literal 159
zc$@*B0AT+|Nk%w1VHN-o0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui02Tlc06+s|7`ohjCjbz{ECmP&OfXYG3|vqM#ivzU7LME`&-6>yI4$0kwf-UB
zjw2`vKpmscb|5&P&}fvG%ZVZrCDNdr4TG1=X5vA9ds)dCOo4??DbS{9lAWu#p=0kD
NK?Z<<f`fwz06X7lJHr3~
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1845e6b2ed71678e1770cb44cef99a7746c54f3b
GIT binary patch
literal 175
zc$@*R08sx&Nk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tD7`oj4=LA4O5Y!kTX6;oN5Q9erhF}B*cL^{Uo}@Y7_&k<*-|w~y
z1=NWZWV%`?CTIbUOeoB0Asq<Vtai)o@_b+sL9#Sbq*KfdC{k-&OIw9KR})`Nr1*PE
dty)D)cvN&@VL%UwiVIc;1CNlAl9QAP06VuhKOg`A
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..676c26ab1376d8f073ffc4ca3a0a760d93711330
GIT binary patch
literal 185
zc$@*b07m~uNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tN7`oj4=LA55pvC}8>n+Mv5yMm&f)NxODqIS?i5qElc&_V#z5l>b
zslx#XCIJ`Al9>^Gl-ElpkVUQ4=ior-dcWYXco;0>dXkPbYg_{gSZj~$1T>44q(^%z
n9$Qm0ARshzeJCnRG<7P4P-bR^50jJ&BoPCdnwy-Ro(TXuhHFKe
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a5834b794723332b10e22e4ed262d813a659d606
GIT binary patch
literal 176
zc$@*S08jr%Nk%w1VIBYw0Ez$r|Nnpi0RdoOV4$F&fPg?iKp?=tV8Fn@A^8LW000L7
zEC2ui03HAk06+tE7`oj4=LA4$AhZ-f<^@JzRF*JIWKa-=$a!nGr6x+=cwU}*-v_nZ
z=S5TzWWpfncpQN+1ScmsI0&xTtai)g`MxyCjTxmFpky4-TN!GK7$S{riFb;t;oN3f
ewMKVtd;n{MU_Uhvii-;-5d)Bsl9QB`2>?6p8bdMw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f190462e8c914e99e146b33cea98725b8de1e238
GIT binary patch
literal 168
zc$@*K09XG<Nk%w1VGsZq0IC20|Nnpi0Rf<(pkQENfPg^2z+gZ?Ai%)DA^8LW000L7
zEC2ui01yBe06+t67`n`N0RW;%kvI$yC&8YiaZ*7A#+7Xy=mKN=uH+2HuNizWE1e7;
z4p2Z52!?=a2wVs^hk<lTrPges0pz!v4KanJGJBmU47^^=WE+}}@TIRLPSH9@5Solf
W!}n@3Z7dCi3Qz|Eii?bl2>?5@7CY1c
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6e94d42c16f22cb06e1e48f3a8248c9f9af298fd
GIT binary patch
literal 145
zc${<hbhEHb6krfxSjE8b|9=A`BjbVv3lb6%8X6oN925?KK!V~=7DfgJHU=FAAONX#
zU=EYmbtaARglDRR(zV*p(^wJ{qdaChEU%rcC7T%2q4|@|IFRM|3&s|=hHHjAeJ4^r
u9hY*9(73Li#mv<idLXg=^-nL>Q*XFWwH`A~3s%iZmTTHkW9QGnU=08WgfyrC
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d8fdc67c045a127ba0157e4a185a59e00aa2dbd8
GIT binary patch
literal 153
zc$@*50A~M3Nk%w1VHN-o0IC20|Nnpi0Rf<(pkQENfPg?iKp?=tV8Fn@A^8LW000L7
zEC2ui02Tlc06+s?7`ohjCx98qEM<bK_Ye|Q5Jg}Z1QCpu2X=6*1z#xNuFV1J+)_17
zDrM*pinGsQz-&67&lm1SiwK9vArUCuv@pI7t-I?{e!1DGg!GDoQ`y)-rz;PFynfH;
HCjbCD^&UIM
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f9b384271cf4eb7d6681a8eb0af941134de107a8
GIT binary patch
literal 155
zc${<hbhEHb6k`xzSjE8b|9=A`BV$8@!-5415)u*)8~~yN4h{;6KUo+V7}ywe7=Qqz
z)`2-eV%MEqH3oqrb3#)(Pd+%P*wdPnDf4t``0KcXzs}|TNqppyS)En9IKeT1A)?Ko
zzwtnh)%^3)xl-LeO)8hJUYZyd#eKkW;+JPSQ(4z@TTOSHZIm4qZTXIGY2tzRzyH^B
HGFSrubE-b{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..84411068b3eb600f50c8963b03a381f9453a675a
GIT binary patch
literal 226
zc$@*^03H8FNk%w1VGsZ;0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBy06+t$7`n`N0Z1Wbsez1WgDJr!Wm{ze)TnVlA-sYJknCyFm3-nB9Am3W
zY62_~Q$yYhHB=dGx8Q`4l%lTKnKkxu6<Gzt>+^-S$`+H1*Yd5U%VpH)^8K`f17Xka
z_n&535P@h}J6mRK6i9_*FoggHGc}5l7gd0DI+a3=RFEc^ECQcSqgbLs0%CG_U~Xsy
cI&&OxO|DZ7DQtl>4ZjK+4+F%-#>NQ%JAc7hZ2$lO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cae473e2211900f54233335317452b67c8c8b13a
GIT binary patch
literal 206
zc$@*w05ShZNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+ti7`oj4@SFgupcRx*>MmDhC|Mw6RX_|Fa0zfX!hzw|7DpR!xwfdF
za7YBGSjD6gb!@$Qp%U#AHJ+Hi3`htPbTn6R#v42y2<WtW&2GDq%Q#Ur(ZXULyv6Ri
zlT%qaC?6g=3LRA@Wq~($H%v4D20Sf_Sa6RhGZ!{d8<k;zm~y0|5T~f8D-r{(uCK7M
Iva<;QI~)E@WB>pF
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1fd246b6e30ba7fed551257263515b79ef231ce9
GIT binary patch
literal 209
zc$@*z051PWNk%w1VGsZ$0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq06+tl7`n`N0RW+dkT{SLXA2jgahSmv+16ofN_tH=cEtjig)~cb4)i*e
z#4-uFRxQ>JQ=lk(%cf-t6&5EbrIly#1z$u=IO=UJoebILKxn()?^jX_;ZD0>TE&=W
zSr%1bA8K+<J_3Oq0w^X1US}6!M|O9KB`1?tVuX4=Kq6Z|c$q|!eOIQSFH)6xAFpc%
L1GBWXwFv+_E>BES
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e26d03694179340a703f3b8a514eb8fcc593fded
GIT binary patch
literal 221
zc$@*<03!cKNk%w1VGsZ)0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBu06+tx7`n`N0mv4_BqPpdLBN_MbV6}uk_U|G8Fpr2dSEInW%{9#Q57K?
z&oipzguzy8msGlRD+>#08(C+}Rxx0})||IaHdXLdbYGRnuuMDALy8!4AlUDC{P2B&
z@Y``wf>aZNQ)7RG9$Z&XEd>HTb8(DHh<}%53LT1)K!8mvXNp_~rU71oYH%-BBdH+~
XGL~r(Q>=+D6uWc>1HZt*!3h96iM>?8
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c23a6bd1be198d9165edda2a68d2498a2898f31b
GIT binary patch
literal 267
zc${<hbhEHb6kyO{*v-K3|9=A`BV$8@!-5415)u*)97u3*P&jblz=R1N4A_9;PZmZ7
z26mukAOM-+z_P>Ogy&03#tcOsaVY@-=WUD%QhlirHBK8REt6`OihjIDZkdhXTXusJ
z4f}i#6rbiTY;p*`;nZlcce$3w+F1W{tBxt$Qe`x{?(^r@lHC_p6vkHTZce)LajuR+
zLXCf*sHP4(OGjr{S5AzRguRGIltV^|i{|8<hUwC|`g1e9Ss5FX;-d?sW#t#<$}F>%
zS-h}l!$Nzxtv(gjdK>L!*@_e6)&zS-L|B{*pSo&&-civjLMr0SH*ej(Ey!RE0P^cx
AS^xk5
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9ed3fa82b294dc727faf5a50811288f9010d8227
GIT binary patch
literal 137
zc${<hbhEHb6krfxSjE8b|9=A`BjbVv3lb6%8X6o997s5D;DCdJg5pmWMg|5p1|0?<
z0I79g_LJCkCXMlgXR3tKwc5=(E*fHD%Y4<d^6vbS%~{^)VlYiEz?>zI=fHx18ObXZ
p+`8Ue-taJ}JuY=+w%5uPVSQ=b6B%wSS>t)khULYUsJRRb)&N_sGA#fA
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0f565549856e7a5772a0980e6e370843f55c279f
GIT binary patch
literal 151
zc${<hbhEHb6krfxSjE8b|9=A`BjbVv3lb6%8X6oN925>5NH}odfZ|UUMg|6U1|0?<
z0I79gj*-}PrkwGFXR3tKwc5=ljDaEyjuA7=R%Y)i%!`y@kXRI#+or}_BIWe>+hG~D
z6H9_-R&Q09?9>oqC0eX@QlmQ5)81u)%Z&|PnmTiiZ7>$BNnc*&VJ^q=V^7?C1_o;Y
Dw4XG)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b0831f515b06ff70901c18f50170a7fe8abe5daf
GIT binary patch
literal 149
zc$@*10BZk7Nk%w1VGsZm0IC20|Nnpi0Rf<(pkQENfPg?iKp?=tV8Fn@A^8LW000L7
zEC2ui01yBa06+s;7`n`N0mw;Z7$VkvvouRV1crra6PlhI#{xtF$TMMjfI*BqQ34&!
zs9^(Q4uhm}xx}?rkjZWqC>n87VKF!<`~tMAuu;9KfG(VlxBI@HX0rTv5ZLc{d;$PF
DnhrP5
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a15fcf0ca71b8a6ff2965f0d88c91b3a8688cdbf
GIT binary patch
literal 145
zc$@)|0B-+BNk%w1VGsZm0IC20|Nnpi0Rf<(pkQENfPg^2z+k|@z(7DCA^8LW000I6
zEC2ui01yBa06+s)7`n`60mumo4MRlACDszr1caAu6PlhKP_E!q1oOpKgqRZ+@NJ^T
z>th%gk4R*!wSq_rJ6-QLIUGE;<x`Obj)u2Xhl<nXreUV<G-_uag1CG>PXGWrC-F8)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6dcf6e076f6a3929e162a00af80c70faf7c0b440
GIT binary patch
literal 148
zc$@*00Biq8Nk%w1VGsZm0IC20|Nnpi0Rf<(pkQENfPg^2z+k|@z(7DCA^8LW000I6
zEC2ui01yBa06+s-7`n`60mw;Z7$Vkvvm`_jfI(ql+LWs3#<c)(%+f)e9#D{Ah--w#
z2xk}=k4R+B#ezt7F@@>(=~bz^U?gy0<+O|&ptBmka=Tz}N@h~X!Z_w3sN3)N1OPi{
CH9OS+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d8d69b9816f2a76520d34ad038c285a581fafaf9
GIT binary patch
literal 149
zc$@*10BZk7Nk%w1VGsZm0IC20|Nnpi0Rf<(pkQENfPg^2z+k|@z(7DCA^8LW000I6
zEC2ui01yBa06+s;7`n`60mw;Z7$Vkvvm`+g9AIH#+LWs3#<hS*9AtQUF#+m?33M7z
zgK#qpj>u#Z=VC!7J<*7T)BQfgA1roQ__WnVAPcOlZkmE_tn-zdRI$AC5ZLc{d;$PF
DDr7n~
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..11928ffdeed8faa3858a030e34e011e3e1ae78e7
GIT binary patch
literal 204
zc$@*u05ktbNk%w1VGsZ$0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq06+tg7`n`N0RUlyr9uWWqLhW86dLD!=(lxg3#?~hC<a-wpR8oJXHA*k
z%al5)h%OXNLP1q}NhJ~kl;VB`l5ja`1bEz#=wjoF8eq<Wz;3(UxabffhXM+L3MEjU
z@|bB?UV%m*V|F@JM{#>!R)vOrS3#6^KbM3c7i5-$b}B7l7GD;UkfA1Cs%i%VuCK7L
G2>?5y7ENCO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7fced1a7f5c65f57da1c7b9e0f636adcffa328de
GIT binary patch
literal 152
zc${<hbhEHb6krfxSjE8b|9=A`BV$8@!-5415)u*)8~~yN4h{;6KUo+V7}ywe7=Qqz
z)`2-zV%M28#uJ{Y3d+}NH;XVSu&`du6rPpzLQuv*u;su{*+Y%osb{@dFYsL1+$m+u
zeas=lYQF#ZWkroOX%RDmxP&f-#i*RM$m*$A<Fm40`nYY?O8w?F`n=71>h}9HFjxZs
D7>PB}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..15abcb58f9bc1f2c54b76ff2feb5da413abfcaa5
GIT binary patch
literal 198
zc${<hbhEHb6kt$eSjE8b|9=A`BV$8@!-5415)u*)8~~yN4h{;6KUo+V7}ywe7=Qqz
z)`7WOV%M28Muv+`6B>IgUbEg*V?3JCBvn3dVHH=rwkX$`Ws?dH)O2>KiMu5$Nc4NC
z6o?)%%(eGxye_S$F4F4n_G`_K3+s!$R=O3-t)6f)wa-YP{Bu@Q(aAk?qyCkpNgDbY
y*GJcx##P6LFts`)n)hX<N8}|;%9TiRND(vW&7QSjg6I-Oe&!V`SFPe?um%88D@mRJ
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b9b982fd6c65803f89d0429272ffefaebbae1e91
GIT binary patch
literal 126
zc${<hbhEHb6lM@$=we{_|G$Bekuf15VZnk04Gj+e|NlR5AmPA)1ByRc7#SGY8FUzc
z0HoG|*;!)OohtPPPv(Ud9g2n<?ky=y)XbavvNyA|HOE8ZX$42cy7v|<*EMzYusI)$
ebBJe~X}E5N=yUy3g%RS?ClXG-t=i7XU=09hf-u_v
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..501cc280b92bcca8548f113d10da902c58b49347
GIT binary patch
literal 238
zc$@+501^L3Nk%w1VJ-j=0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04@L!06+t?7`oj45S|kN2trf~v^9o>Wn-mWLbq`uF>GZf6k28kg(ZOcd0{G9
zs`X+SkI1Bw6L77T(CD#QMAb6E9S%^a?6RcPb;fk+3N%*Qf=07uDL0uWEDsKZynfH`
z`~QDcQiD=W6lZi9XhJz0WL#K~If;=MW>!xgB0~lmIT{#UK$=EWFkx6VH;x#qH3~Ig
ojh0m<ZyQ}CtR5$$BbBCv!ce9W#>dE169df6&d<=%($Wb4JH4)3+yDRo
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e17b5ac2a62489f18ddfbb66e08328f9c8675ba6
GIT binary patch
literal 182
zc$@*Y07?HxNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tK7`oj4=LA4O5MnATfH758S;R0^S9U605g39I6k|}HW3KO%ZSp{%
z568)1Fc*&SHWCyHEt)fgq18$Uf_BU8dcVJ*_$p~WF%+m3a9sD8DCEVJ{8a2Hcn_&E
kDpf>7HAog3EiXtQd0}H?Ll2OV3s?sOmY0~Bnwtp#JE~GbJOBUy
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc4c901492e4303cee565b2c6655ac2e0cadc0f4
GIT binary patch
literal 207
zc$@*x05JbYNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tj7`oj4@SFfZ5P|}uK(63beU%szgLY-cNM%^inpqJWScz(2@Bctx
zU>7VJg+xoN5U{;gGNmgd=nYe&f(^9Y`fP$iFKk5}2<WtW&2GD~$GCAg$$Gd|aLywJ
zY%zd+S1K`09#2y=JSIADP#ZW;fF)IjRAr7a6-<a@P?b_AaB`$RgAk~x5M~DhuCK7M
Jva_@a06W3yPK5vf
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d7b963aab5e231ffd40ee462e27205aa5120fdeb
GIT binary patch
literal 178
zc$@*U08Rf#Nk%w1VIBYw0IC20|Nnpi0Rf<(pkQENfPg^2z+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tG7`oj4=LA4$AY=lgKqypJS%aWeS7wA0hkc`0o^fr*!F=y~ZsM=P
zN5o0hd^7-|P#{#Al;-kSIt;GZtai)&@xG&+BsO(M%~B9f7k<G+myj97M!hx$kvy;p
g*DZGdLM<tLYhGYrNDqvS3snaKl9QB`mX`?tJ2G`eYybcN
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f6cee264b7a9e089a614b36f998f7a23872d1ca0
GIT binary patch
literal 267
zc${<hbhEHb6kyO`*v-K3|9=A`BjbVv3lb6%R;>yR4b^)5xbVP%grXwLh6V>qOPRht
z_X7tG$jb6DfPvyq7DfgJ9tIr{2V{l=%MODRo|?&w8O|n-QUW|q&q|{N`%+H`e%Lta
z*~B|LbS|yi_;UBOX8{^wV#bOOLOB*RsWH4^4#<qSIN{r=+f^H*nvYEH@v{zFA*L8O
z;p#oz3W*Gni7}}!7+SIg6j<|%3q5(5J370%s#=vLTBBOnxeR#yTiCc<^HLSlL+8mg
zaIj>yOl(;uw>&mTWUZHrTScAs?EG!%4wK#77kN)-<l4G-Dz`#qWM3?&C?n^oiK*wW
Ps)#e)ymkAwAcHjk0sUfT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9a283b0ac38526d84071960cae560b9ab3c70c49
GIT binary patch
literal 186
zc$@*c07d^tNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tO7`oj4=LA5503{S)shA&?Z5%O7)s-2XA$%A7v6YEZc&_hxVDrFW
z?Su;$j78UH6G{zl0umthdWou+qUk{BdcWYXm?$jw2ohXW#H^AE*fW_EMbe$k(X*(r
o8(&CGcO`Qj07or=EHZY4H)dr%Cl8dB3tI;Rnwy-Ro}UQ-I~eXq+yDRo
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3132291843af4d4c23e7c7abfae8b8dd067743bc
GIT binary patch
literal 210
zc$@*!04@JVNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tm7`oj4@SFey1sDXux6PX-WFi?51ND)WVPF<#T!Fy}MF^r7>;FLC
zDHSXlO}t7ElWQquFO7{;+7SykT%kb1Wx17ab~HQ?&gisy&2AHqaNubI!2WQ|Y-WrF
zV}>eA7&ZZ1D=RvGBUXVdF*8pBGh8({Rewn_99TUu9+OfxIa6dwai>Tr5UZ>ZC=vs)
Mva__cwzmlYJ2Hk!xc~qF
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3cb24dfab40b8b159dd592f4ee67a991ea73a5c2
GIT binary patch
literal 244
zc$@+B01N*|Nk%w1VK4v?0Ez$r|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui05AX$06+t|7`oj4Fotsi5Ef_<#0G}3VOOS+pi*i@P;dibp<7@Gc+uX5TjD_5
zY1YArV6u;L$!t26ftcw@tu~`cn#Km?c$64m0n-{2YaXm+EWQ8*FE^a^hJOKL{JR!A
z4E}(Df`f#GhEi6EidzE}dSGvHZF+lmd2Bd*SyNsgAse4s7(OH@Wk_cqT$vpuDq%S!
uA*Cj*YCky~H#s{vLa;$BuSG(ri^o)I63fiYeFp^5($mz{*4Nks2>?5fxn79?
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9c84f46b90bb99c9c42ee6370cc0ded92e8c8d5a
GIT binary patch
literal 143
zc$@)`0C4|DNk%w1VHN-o0Ez$r|Nnpi0RdoOV4$F&fPg^%|Np?iV8Fn@A^8LW000L7
zEC2ui02Tlc06+s&7`ohjCx8ivq#zKS#kiBjX`=^nC>EG$ORXO!s+-DE2B8y1)!T!E
xU`Q+)jWJhi6~W{<yiziB%G6#r>gYOwoh-W^30PHPKaRA+0~xsA@OV4{06WS}H){X@
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1851430c25d38d7a66bf7e8a5654fe12886cf88e
GIT binary patch
literal 187
zc$@*d07U;sNk%w1VGsZw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBk06+tP7`n`N0e~W^Ei#Z1rM=nK2~8k`oCFv_5f~WSsf7WnTB`0voF9as
za5&UWb^@Phw=ytuqtXcgRk32bDuC3OYMEQ_68s#KaRi8`HMz=mtSMT@Wr&Su>X>3t
pDDf^%Sz~nzcO85me=~VsOcifrka{|aAe1GUKL-Pyo}Zry06TNnMl1jT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..722011fc5caaefece4661951121824b779efd103
GIT binary patch
literal 248
zc$@+F00;j^Nk%w1VKM*^0Ez$r|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui05Sj&06+u17`oj4Fs^d~0K(oIgfLsj38AMM3SfX&wgJIFXztq;f$<rIsgs=y
z%Z1aS3O1SM#cVpCP-bivty-^B+H!=;36P^w2G_HQp4m&!^TmMKuXd}@+tgbga7cC-
z`2T=`f`f#Ge^ghAihC7mByn#Zcx*^*j{tWVc~VL(TQDXeC1MJd7AqU5dx$lom>&UP
yXP_=CE+QEzt6G$xMX<7$K^k3{UP4KTi_2A663@`lQxpW%*4NnC+S}aL2>?6Ku4lIZ
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9afa0690e66fb68e07b77b1cb2309c0c58d55df5
GIT binary patch
literal 188
zc$@*e07L&rNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tQ7`oj4=L7)6R3M0IgfNpujTtda6_#mZU=)<)xl~}HWUlY^&Hq2!
zDW>trD4h&UW-;`JfWoG*T#~3#o$x^DdcWYX7z!-62oj2P6BWSJ?6&a?wP*?oHvU8G
qm+BgMEEydvOmRXeA{Z=#88ccwW|N5zmX`}A5d)l^o}Zwh2>?5Fh)P)i
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..55406887839deeee4c579141ffc25e07a0cebae7
GIT binary patch
literal 214
zc$@*&04e`RNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+k|@z(7DCA^8LW000I6
zEC2ui044ws06+tq7`oj4(3k*#pb7+GY3<dKUEfv(#Nb_?!d*ff2S-JcC#R*}=l{T9
z5Tz0tk3*hqBQwEbg-an2rQkF=q9+O{6fEDUOu(&_EioU_Kxn()@VI<lMB0z2i8<XR
z_s13=TxWhebu45qARjDWH$5hXD;q9OOk^Yn2ahFLN+21QV>nYSn<6EjcdI{I5U;Qh
QDG~#<wzs&sy1NMgJC%=77ytkO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bf142db3670266ec87046ae4d8e9223e639e7203
GIT binary patch
literal 202
zc$@*s05$(dNk%w1VGsZ$0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq06+te7`n`N0Z33xFk%KWBF$5{by6XmXd#VW=mM;3Dk{u*=eyog?t`((
zX;BO6G(3O+qXg|prDJf3Iu(<@=F?-U3a-$CA}7K&0zl4zz;3(U(Blqr{B9=|g`pfC
zGm&v20%&(yI#Xw9P-HJt83ih2j#`pt4T>#th?j*WgEWPojD=lQU}vZ!4+E^NuC56H
EJ2{X|6#xJL
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..742c9f0053220c3c7e433b086a2e746e52883577
GIT binary patch
literal 337
zc${<hbh9u|RAUfeIK#m3|9=Yu1H;m#OOun6otzZ6ZjCy2ELl@iKtO<_rNv26QQ-OW
z;$z2-85&9~T^e-lTDF&$VsWu$a<XA|wqZ|?69XZj10q0nF|b}sQ0Pm^oTqV^#o_h7
z0-fUrH=L``yUvu&!W({oA;QC@-KpClONZgiMBxL;qD&m_*&G%r+!Gom6&Q$cad2#@
z3G-OdEcak~K+f5u>kk=JUtDFW^R5dmX5@|xVH4ER<J4i{Xk=&P58&by?BOgZ3TG(o
z>epY)GGiu(aKI!EMv>@3JDm<b=Ws9G>e{{ub^IKTb2sUh#>DX@RHme{vX?dLmK<W3
z@4D8-Z7uJPK#yq`bcLt3T0OOV^6aHSsK(oO8ihQ}pTB(l_Wj3CCM~AF|Nb*DbIC|B
HF<1it69a9g
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..65fea0a9491d77ede46997fb49eeb9e4318af8d9
GIT binary patch
literal 279
zc$@(j0qFimNk%w1VGsZ;0J{JH|Nnpi0Rf<(pkQENRaGjgs#V9wV}O7_a&kF9Kp;6e
z9KgW9j*dqi9S-B;aR2}SA^8LW000XBEC2ui01yBy06+x9Fvv;iS^;Q4Nb6fL2-#LB
z2(bYoxvJ{gmVgl)N0Njiz5cTmVpu@%T&rS(ar6-!if40U!|A3!+fEZS4HX8gMrDk#
zdapo-$wgBO@NgTMM2P{64uO59*Wd+meKbBeb3Q*}T8S+S1CNlAk$#D77%u<{9CrW(
zoic7?n`T{=cLoG%f~6d4ft;Oohjl5SeyDJKtS~^KHI=(3ud^#Sf`cJ~2?xY1%FM{c
d2gjuqH_aLe0o0+^&@<NIBNqbY=I7@T06Wh|Y&8G?
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..aa904093112c5ad8552337b768e7db12325d476d
GIT binary patch
literal 233
zc$@+002cp8Nk%w1VGsZ;0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBy06+t-7`n`N0Z1U|l!1&mS;ZPB8HQkX;YA6>m2GMaydqGVEeKC0j_xB#
z;WJBNa<&gmWe6aPK$)&abQvW*)~{9~A(uQ>4U82uzt{4U?3|RQordz-2+Riuf_~5E
zN2M7M7gbvqH(GFRZB|iTh)`5LXi-A|1(Q@3j5UC1L_}nk3I>~o1*D*9l~rT~c4nlB
jGlO>`t|lafQo0wev5*tKF`=Csb;lYH1Ix_K%?SWI<ds&)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d995bf4f7f78d89091cf7c0a82e9864fa5be44bd
GIT binary patch
literal 237
zc$@+4022R4Nk%w1VK4v?0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05AX$06+t>7`oj4FotsiD4~Fxh24QC03P{mm}YK3$hO4r8KGyGf<V8en2)qv
zrXV!rK(W(n$!t2GNEviWod%LCR;^~Zv3fNDQTcLdv8bGi_*4DTztKg_Q$-JiynfH`
z`~QGwRfB|A6)bFPaZ5yVi;iw_Dpyh|C><XqUly8|ZYO3@oJw0cGzF+DK4P60T5_Tr
nK{hx#n6#@vTXvx^QiQ-%loG_n#xWEF%FE2n&d<=%0|@{-6TV{w
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd8dca3505db6220c29d4b12b5ee0b0c87166899
GIT binary patch
literal 169
zc$@*L09OA;Nk%w1VGsZ$0HOx~|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq000ASc)HyFFv>}*y*TU5J0w^jjwGoBK&q~3FdQhG3PL*&u^iNZi_0yZ
zFUQ*1egHwq*t^9Fw5XtPBtoaFp~^rqsI-7WfEpfGXFT*dnP#uWWcV7u9eL+r8W|64
X;+B9n2LptKhK3*q1dEJ~jR^odmsUY|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4f03fdfc01aa9995620599239b59dba1e5c01db
GIT binary patch
literal 246
zc$@+D015v`Nk%w1VKM*^0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05Sj&06+t~7`oj4Fs^d~D4~FxK@eN$ft<E|f(01HNs0k6s0JFeo*~pifA=d}
zE7hxMe#VnbC2BgK&}cI@lUlD>swD*jAv>cDw@KV}z9wy`&@%x9?hstW23}qT&3r05
z5dMIHf`f#GhJaOAii;sJ6>DvBJ#&+hcXoA_m2PSnCZ1uT9~+=0V_~DBOK(i5I(wmG
w3qEFzubitvJ~*jeAv|VmDi~fbjk%1;R$3Cx&d*d71Jl&i*4NnC+SCaEJ1-AnDF6Tf
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ec419c97c1d87fb677c47ae5971389fdb164c5ac
GIT binary patch
literal 236
zc$@+302BX5Nk%w1VJ-j=0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04@L!06+t=7`oj45S|l22?baTg3w_1Y2KA>g-`*8LK4H;3aUXG!b}JF=dqp|
zKsa0lV5^XF$!t11$ftDbJjRNlA1}udfr3eq%A|T-H7UVqxCW`+r*wQ|8Ceg6ynfH`
z`~QDuRD)DU6d-bLG;fPE8E<uvLx^@!CTJW#UYjD9C@LIfP*<WPK0RxiVqst`I7U%G
mJ2sqObU!*gSR1f{guhKz5yQmA3NRA`%FE2n&d<=$2>?4Ps$CKQ
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1c94d0681f91da909bf71091683b17a274afcf55
GIT binary patch
literal 136
zc$@)<0C)dKNk%w1VGsZm0IC20|Nnpi0Rf<(pkQENfPg^2z`#I2Ai%(2A^8LW000F5
zEC2ui01yBa06+sx7`n_=0RTcIl`;$wvG*GHjX>Cun2CbhX($ydP6lPv#8I|ux)p<<
qa5$XxG>~3~r&LV>lz`4RyG&xsY6G@2uAIl#cKj;{&ggVH0RTH(*fS>p
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..812b722d810b250025013e55a66503647ab0ea38
GIT binary patch
literal 197
zc${<hbhEHb<Y!Q3Sj52a|Nj{<m^pK18W0#88#90e|117vVPs%nXV3w189-_on7bl&
zt@+M+!qb~W;Zp1gj$3A$EE-{RE4`NN+V+rheU4POvBH}@6K+~H7i9dHn#a_nIO(z`
zx834bl51s~z1vKbBr5hdzg?*<#@Xe2YUiHF^XFU^?%@8msaz((&BGz~d>mV7zAHnM
svO~Hx8*@cVVMdj$O^%Tn?+i_LMwXe}s<Y?Lo5je?vV6r#c}@mv03bC<_W%F@
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3173a5ba6752624239cfd0d49320f39d8cbb7ba4
GIT binary patch
literal 164
zc$@*G09*e@Nk%w1VGsZq0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBe06+t27`n`N0Z0=>sS*S-A`rqCW*X;dD41<s2EN5=lC<1PVOWgiEyA`_
z<P?-#6fqLZBWPfH2ZD4;rTS_z$STEKu9^ZvcZOAxQAo3|Qn3_`ZkqRF0Ep$}a9A9l
SmnBP1f*cP6hKGoV2>?45sytl)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..aa9502feb225a88c993cc7a6b0c6691698902a71
GIT binary patch
literal 232
zc$@*~02lv9Nk%w1VJZL+0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui04e|w06+t+7`oj4kew3%2*O%X1g{ui1O~u)1?XWybrFLbbZL1N_PiF_oQEwL
z%%v$BkH}<isBAiu0p{&f>Rd{?77t)0U0PpZY-8IL4F*9ulhL5nCQ&;&I1ujmynfH`
z=f_WhPf-*b9&i?E8iyWdZ6=6~FMuImA{bkhV3!;g3tS4GQdv12Av%>)r$HEEGLM#?
iEo~{WVJj=5fP%b8bP>S8z%Ua7#>dFX%FE2i2>?6UTvx~d
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..14d4ec20ba46d0854e1a800c028ff23dba76d612
GIT binary patch
literal 143
zc${<hbhEHb6lM@$SjE8b|9=A`BjbVv3lb6%8X6o997u3*P&jblfZ|UUMg|6U1|0?<
z0I79g4w2Y(r%Jtn(@W#X1n<KFLaY*u8zmR9cjc^Z%l*?8?NuW0ljxGTK=^8+gN{`H
vkx(DAjx80e*K&@p3}L+Nxwe@5S;UearLVEOiu%4hViw$S|HBSzMh0sDSr;_o
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4ce095c6f7505cbe173de0a3bc269ba7f72c811a
GIT binary patch
literal 139
zc$@)?0CfLHNk%w1VG{rl0IC20|Nnpi0Rf<(pkQENfPg?iKp?=tV8Fn@A^8LW000L7
zEC2ui022TZ06+s!7`ohgCx8h^p@C2khLDsI6xOwM-=?l8xW4Tsj)bAcDxtI9G5o-w
t@RxeQ29cFcbMv?=t|!O2GFSpO3^hb6U{70P^W!KldIy1e&2Fm`06VU#HcJ2i
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e3b501c13e5892bdf173803099b7dc712afa94f9
GIT binary patch
literal 232
zc$@*~02lv9Nk%w1VJrX;0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui04x9y06+t+7`oj4(47;2C?JQ6wGb6hbQ@4+=&2DyWdsEWyzyvlS74ZeS>vEs
z&%_F$j>x2Pi3}8(&?wZ|nkiyCRR;7a=y<-|4xD;!KgZ9|Fr4iK?{QjA92^MvynfH`
z`}tK;f`d*JC~9eFGiq>KZ)%T_D^(yVA{{)H9$+V(ZFNR$UN3EL8(t|rFduSSR4%Kd
iG%}i`oS&OzfrGqEuMxn(!7LL4#>dFX%FE2k2>?5f#9r0_
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0d32fed439b8ad650a0263a03d1535f2a538c844
GIT binary patch
literal 230
zc$@*|02%*BNk%w1VJ-j=0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04@L!06+t)7`oj45S|l&FdzpZYPR0DeSm>!Le`N1F;qohTv*55p*C|xJe!uw
zMo<8>UZkXQ$!v;TIj3}*Ji-*SqK&s=?NTFUR|EarGKCxWrd1b%sZW~aIuP#oynfH`
z_mNbAfh`nf9B67pafWOvhX846WJqHbV<1(FB_~F4msWB@X+w%pGG}3sW;vifqFXqP
gr#!AeDy(IKx=vORzQ4dn69dG>#>dFX%E}1<JK|biA^-pY
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dd739297582702a50b6a69549518664cf17f8607
GIT binary patch
literal 222
zc$@*=03rWJNk%w1VJH9)0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04M+u06+ty7`oj4P@NNiFdzr9x!~I8ftgj6KtK#t5f~Sy2<B-Sn2D05%A&xa
za2WL2h{$Ab)l$F;DbVKRy6H+h4HNsx2%xk=7>X5(3g!>gcObam@VI<VcmI@lq>93&
zS-xI=USwh@g(yZ>DJcp728|go0boa2DO(w0k1iZDCmxTAqL)7|Fq<8ziXI(bBY=r{
YvPDc0wzm%}69c@xzQ4f1!n_FpJ9-RQfdBvi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bc577ab80142c8b2e62c72c0688e3ad6f3026777
GIT binary patch
literal 215
zc$@*(04V=QNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tr7`oj4@SFguFck!GxuKg7Qksxu0Wpw35f~R%y~Vr%BKclHt*NY&
za7ZlvR>q|AltNZqJ0DC_+kiwf*vHol;y9L5p&+Q4$QB<{bs)Ik@VI<VcP{V5)I`WJ
zWzZI7fq@)qT^U$2Pa84|03SMjH%DG%TN*GoRtkwbf-^vWJ6n?_BOH-Khj^@OD-f`;
R5Nrnnwzs&sy1Tpy06Vs{QZ)bo
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5ff6bfd92f9eea7c60098b6c7d4a615bd6b0a487
GIT binary patch
literal 207
zc$@*x05JbYNk%w1VI}|&0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui044ws06+tj7`oj4@SFguFckzLXx3cEd4}=@#NYu%U|g8kVE}Bo_nEF=@Bcu}
zE=VluRGF4bP^fKYEXu{%Ds+y#8mD6Y6q*^PAUV#U1_y$A&2GEjaHMe#L``}jZm4Vl
z*T`65D^ea;051Ve9f?kXUKfcnWg;bw28fPPFC|tyhE9e`nRKKTXAr2Vs3{TyuCK7M
Jva_@a06RAbQGfsd
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..316750a26bc6d8986c8ee8ab8018e02d5b468766
GIT binary patch
literal 235
zc$@+202Kd6Nk%w1VJrX;0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui04x9y06+t<7`oj4(47;2Fdzq^xvhYK0UOB`LGfiQNemTgTt*=X!F+F5YW}j%
z?WTEwTF9hwxeOSY&?wXi1E6vORVRbH8GNN&j@7+ssmEa}o3XJ9DmI&I9THuG17Xka
z`~QG}e^pY2hE5b@cXnAeLt1iLaCLS?RX8k1B`aHDS!0|nXm34d9$jCV911}~W|lEn
lU#46jD66;`sbzPghQCur5yQm9FB1dF%FE2n&d<#W06U;<T@wHR
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3d97c4a3003873c41cff132c1d24988a563452b2
GIT binary patch
literal 220
zc$@*;03-iLNk%w1VGsZ)0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBu06+tw7`n`N0RYj0kb#USyT=+QTpzeeBVb%9ke$<26tT&b?Ryu7HPWsS
zid52-io&DESWD%SN}HrGs;;Dxo&gD?Dw&i9iKz+{79BFWm)0Bz@VHzKiv}TftdliP
z?rT9^RaHP_A5V3MeK27Riy~%6hGz?pQvn7*OG#dmek+58encN+KvbGwTLN2Gfg)Rx
WuBHMswQU;}x^4#pzQ4f02>?6yxl(EX
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f03a4805946be365be77306685577d31c80a58f0
GIT binary patch
literal 255
zc$@+M0093-Nk%w1VKM*^0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui05Sj&06+u87`oj4Fs^d~5C-TVcE1*2WJOSDWg&!yB4*mU5rb74n4zw?u==f2
z%NNM-Vzwg2G^=Tz(5Q4utu{l}tTr2<C6y-+5@?b=IjfY6GwnKKKByq9dKTzDy!~^@
zpJ@jKf`f#GhKGoWgKt}njx!ZcJ|B~LJANpb7kiSLZWd+$SZp9?b4&ng3MVonPp+a~
zdqH9#OGr>?79(pND=x84H%nopW+fd%N5?M1N5NQ+(pH}m*4Nl>6a(Dd-rwNi;^W;3
F06T}fW;p-=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..775438137516c30600bb55aea095ea04b0435662
GIT binary patch
literal 183
zc$@*Z07(BwNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui03HAk06+tL7`oj4=LA4Sp&$q`spgpG5km(UL1A5>w|#{fkS1o|_&t|-?~gnR
zDkU%gTAA0TZ~@ki8{0-8oEAf*17XYUdcWY{Z;X}Prd3SQV72W`$VvQFk<o7K7+a>a
l1dJJXLPUBQDltbee@<kLfh7--k_%Y}1DBYYnwy*n06RzzN5cRB
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3ff912b6e50ba6a42bc32739d435e9092a62803c
GIT binary patch
literal 181
zc$@*X080NyNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui03HAk06+tJ7`oj4=LA4Sp&$q`sm=n11;o$+Mo?H6H-@Se7+!gbc&=ym?)xMY
zCKaQ(Jg`+^RuhUgAq-SX!vzn7tai)odY!-Uh#<jDQBi=v2(9wK$Bg>)`GA@?^wJQo
juhwH=DN0N+OGr6Ed162|508)wB@qLamY0~Bnh5|qRY*pg
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1000a600a9758b451a2eb925449fce9d1db3549b
GIT binary patch
literal 230
zc$@*|02%*BNk%w1VGsZ+0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui01yBw06+t)7`n`N0RSVUwSkOyyUd&Cft*l@;6bcx+lEpR6r)z2lKI&=4(I?<
z?^gi|iJ~AciCIo$CV^oG1IQLMYN-)89fJjvtXZ9jIZBv;A?RvzT<@~okXM;sJOKiq
z*6wQyb{uO3eiwNZQiyW_ertn67Dh{oQHyD423Lk;C0Q|%KcH5kPYRuHJ)1M0Lpqc&
g0$~NTriUFzK!2Z?m`4;zBwWNA4+F@_%E}1<J1KTnBLDyZ
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9ab320eb9a62c9872bbd343d7a6673ae28d5aa79
GIT binary patch
literal 216
zc$@*)04M)PNk%w1VGsZ)0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBu06+ts7`n`N0e~W^Ei#Z1Wi3WvNPxzXpfZwXCp3YOZLVAacS(~xF6$?p
zL0}jTXTjd<*XlWeohNJOtLB=|EA`c2Zf#&>REdE~3JT&+>{<7)Ij8ABsN3)Nq*MoK
zPcT|RH-lb+Fok1MSWbZ*6c%c1dy;4iOOk|DW;lnEC|qT5M{%2HAxEBNa$kyDLy)0V
S6s;UEwi^!vy1Tr*2>?4bn^c|v
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8c905a62681aa8231ec3203d67009db5c0e1cb8e
GIT binary patch
literal 148
zc${<hbhEHb6krfzSjE8b|9=A`BV$8@!-5415)u*)8~~yN4h{;6KUo+V7}ywe7=Qqz
z)`2-vV%M28Mh3+tON=H6rf*$vtdTXeCAz(FT82P@&S~ZB?yLeP*AEXT38n5}_LJJ@
zbE+)bC~$)MDmDuPKHcZ9K3!JYeI<7Dwp2;h_Jy92+O~x!empZ=ar^yu76xkorQ|pw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7932f842898677e36cb01bea594e3afe29290ad1
GIT binary patch
literal 222
zc$@*=03rWJNk%w1VGsZ+0IC20|Nnpi0Re!3K%k(YU|?WCKp?=tV8Fn@A^8LW000L7
zEC2ui01yBw06+ty7`n`N0RSPSwSkN%O;Lq`X&m5zqLghCbzSR0%yeC|Q}wE3TU-U*
ziX-@0f;^nd1?%N@$r3c$Y6OH%(<cxbDUA{&U}!mUQ)6clh*ee$XzIk;Cer0od_Du|
z=yqfiK@=1zflPo|aZNa5gCAZ*e@|(RTojOcQ-O|{C5MwtoR>wPS$k>~h;l_mgNBNm
Ysj^>$g>nXyj8?oc2Lr&t!ompvJIA0_h5!Hn
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7efa66c0479a33889db9d1baef515fb94679c6a9
GIT binary patch
literal 146
zc$@)}0B!$ANk%w1VGsZo0IC20|Nnpi0Rf<(pkQENfPg^2z+k|@z(7DCA^8LW000I6
zEC2ui01yBc06+s*7`n`60RYkhkzt4k%9S9daa8kVn?!t}C>TR5&vV+|C<p5M2o^UN
z>98sS0l8o+sq8@{p5p4r+~Is7o)9XXZYQiIw!}D%!&z(-IjXod4}pA6rzZdaJA;ch
AMF0Q*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d1e887974fd9d2cba5421104aba342dbeaa1d86
GIT binary patch
literal 225
zc$@*@03QEGNk%w1VGsZ+0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui01yBw06+t#7`n`N0RYj0kb#US`?Q$G6+&qi;U<-ymkkFY&or${24i$D2Nb!$
zjwf1OSS&!V<s;sbEoCvvoI)oT=`AWiX-5iyA)DeLkJ;s?k)HCRYLcnsRa4kyYIUoZ
zLOgO_c^_T{AYVovNpW*@gB>Iabyj0oE^a?Lm4gL>Ka)>rmWUH$2BvL%dUh45O-gW9
bt&g6Up{taQpd(~^6~8YJ1H;6{#R&jAOpsP?
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9b73db72dd45fa921cbac2fd2ddc61ed35aabde5
GIT binary patch
literal 151
zc${<hbhEHb6krfzSjE8b|9=A`BjbVv3lb6%8X6oN925?KK!V~=7DfgJHU=FAAONX#
zV2+X4bta9GAt*!Dy-iWcqD7@ET3yWXBdcOSm5X)O9K$;m^JW+S_uA;G;QXk<&Q_{l
zC|juhq@amcb3nKEw6LWutxZA78xFo=N;TGKyc4we@SfM*KI<h}e(Z^x&%j^}0E<mF
A3IG5A
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8d730e7344b6b1bd6a7330400a7009f3ce19f8bc
GIT binary patch
literal 147
zc${<hbhEHb6k`xzSjE8b|9=A`BjbVv3lb6%8X6o9fIxzSgM#8u7DfgJRt6mgAONX#
zV2+U3bthJ}fwN<Yg20^i9V~?zi4ro3q7~xLi(Y>}r_~+#q3x({!V8fm#%G#5eJ7R#
xX)Zn+Hu2>8EepA_&vNFm&-swI*Ju0WwJoMcHWeQ)+97+iDZy|3?YEo^)&S@oI$i((
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..75df2c018d9660fd3591e7f2e001e580f09028c5
GIT binary patch
literal 200
zc$@*q05|_fNk%w1VGsZ)0IC20|Nnpi0Re!3K%k(YU|?Xtz+k|@z(7DCA^8LW000I6
zEC2ui01yBu06+tc7`n`60RSOpr81BaXA2deaS~9JsJL}lnys!oc5ZR1<aAK{JxeVa
zEQb0KOGb<`l>9J<u9mS766S)bDX;gsI=i&v$UrEY&*$7x1zCe7HdGwPy4c@3!C|+<
zuZ>YpYAI4fR9gZ*Ls&(NUvxlKS&j{YG&fdtL`geaiaAu9P+}_|rW+3fs;jK52>?6e
C%uK`p
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2aa2a97c00e732613a6486704c8f2297e544314c
GIT binary patch
literal 276
zc$@(g0qg!pNk%w1VLAX10IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui06G8=06+uT7`oj4Fv@UF06<)<F)o2&1O>Nch9HbUAOK+5d9A9w0Wr8MU)(kp
zK%^R}N-YC2qzYwtDvrpL+tIGrtai)2R!`lqc-+!$W=~rQMDn1AxDr!iNFQOB73TYS
z^=)@Bem`zB1wTj`f`ErKI64Oel9QB`mY0~Bnr393o>(~+KY)vBNQi)bf^MXxQ5=bU
zPi|mILbDzqdNn4vG%0OmR=z+2YYK^POfE?`CTeLyvS`ICbwk%^%zMs5c~DKX!nL2}
aVP6yJ>gx@V2Ltf&^7Hid_V@S$2>?6)7jhN=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ab6c02bea920825db9531cadcf2e85531df807ee
GIT binary patch
literal 135
zc$@);0C@jLNk%w1VG{rl0Ez$r|Nnpi0RdoOV4$F&fPg^%|Np?iV8Fn@A^8LW000L7
zEC2ui022TZ06+sw7`ohgCxAHvnMBechTa#DQ2^(WXlj0`+OcIgZf|N3gn^oe;Qzp&
p@6>8>BB<QtMq2G;EN2titdTM}OO;sMy&T|02Qny|&**Xj06V7gH+KL4
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3b6717a83b8e53528b82740dd93da4cc5eb53728
GIT binary patch
literal 154
zc$@*60A>G2Nk%w1VGsZ$0HOx~|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui01yBq000ADc)HyFFv>}*y*TU5yWc@5j-wI)XsV*YaGWbD2<$+>aX<s@9kaV0
ztS~F;YCeE~bmZA^KO}59+BuWN;<6x(&bq(vb*SBfsUoW|s#>$9%((3^sN3&%f`Y*B
I`~3+3JIpLZ3IG5A
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5ba1470c8d73952cc8d0e83c9d5f76504c77f1c4
GIT binary patch
literal 133
zc${<hbhEHb6lM@$=we{_|G$Bekuf15VZnk04Gj(l4kS1@C>%I&K=CIFBLf3FgAM}_
zfYdrLdr9oNQ>EVE>ABFNLot)HMKI>(wZx2*OW!P6n~^B-vN}xVmz>l4{|DsOEERT1
lV(~uP!nu><sAB4|O;;CqYhFw(st}hxk>H~@`#2|qH2?w@G2s9J
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..22cc35c18fc58ed591cd4438f83f4de9e9cd512a
GIT binary patch
literal 187
zc$@*d07U;sNk%w1VIBYw0IC20|Nnpi0Re!3K%k(YU|?Xtz+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tP7`oj4=LA4O3Bpt?1fPJRQ2{Z40JaHKHhP^A6r_n(c&_K=x&OeL
zZxv!$CK&)MGZWq{MhmSXC`1d>-hsgFdcWZCFi74IB-E)=U8Pt%Z6_7vsTe%8I?33(
pi7rzxGD;YOW@98OgmZcqd^Tl~DK-z4mJ22k1Dl+ko}Zuz06S3{MIitH
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..96f09f99092e56843cf258db571913502c6a0c21
GIT binary patch
literal 189
zc$@*f07CyqNk%w1VIBYw0Ez$r|Nnpi0Re!3Kww~CprD|@z+gZ?Ai%)DA^8LW000L7
zEC2ui03HAk06+tR7`oj4=L7&sFeVf+6$k>rQ6v=%!~|p%#;Hok37kQmX{qmgiL1RJ
z??<v|L?GG>NxR%oDnWs=*;J;|N@#~W48Gv7cudX-&%S|#I@NBrRjo2@{$M6AX$(mj
rnV>}qSRgSVOf+;V7%c`P9)^B8L}-*h50{t=C=mpmo}Zwhq6q*yki|rh
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/pref-composer.js
@@ -0,0 +1,221 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stefan Hermes <stefanh@inbox.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch2);
+const browserPrefsObserver =
+{
+ observe: function(aSubject, aTopic, aData)
+ {
+ if (aTopic != "nsPref:changed" || document.getElementById("editor.use_custom_colors").value)
+ return;
+
+ switch (aData)
+ {
+ case "browser.anchor_color":
+ SetColorPreview("linkText", gPrefService.getCharPref(aData));
+ break;
+ case "browser.active_color":
+ SetColorPreview("activeLinkText", gPrefService.getCharPref(aData));
+ break;
+ case "browser.visited_color":
+ SetColorPreview("visitedLinkText", gPrefService.getCharPref(aData));
+ break;
+ default:
+ SetBgAndFgColors(gPrefService.getBoolPref("browser.display.use_system_colors"))
+ }
+ }
+};
+
+function Startup()
+{
+ // Add browser prefs observers
+ gPrefService.addObserver("browser.display.use_system_colors", browserPrefsObserver, false);
+ gPrefService.addObserver("browser.display.foreground_color", browserPrefsObserver, false);
+ gPrefService.addObserver("browser.display.background_color", browserPrefsObserver, false);
+ gPrefService.addObserver("browser.anchor_color", browserPrefsObserver, false);
+ gPrefService.addObserver("browser.active_color", browserPrefsObserver, false);
+ gPrefService.addObserver("browser.visited_color", browserPrefsObserver, false);
+
+ // Add event listener so we can remove our observers
+ window.addEventListener("unload", WindowOnUnload, false);
+ UpdateDependent(document.getElementById("editor.use_custom_colors").value);
+}
+
+function GetColorAndUpdatePref(aType, aButtonID)
+{
+ // Don't allow a blank color, i.e., using the "default"
+ var colorObj = { NoDefault:true, Type:"", TextColor:0, PageColor:0, Cancel:false };
+ var preference = document.getElementById("editor." + aButtonID + "_color");
+
+ if (aButtonID == "background")
+ colorObj.PageColor = preference.value;
+ else
+ colorObj.TextColor = preference.value;
+
+ colorObj.Type = aType;
+
+ window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
+
+ // User canceled the dialog
+ if (colorObj.Cancel)
+ return;
+
+ // Update preference with picked color
+ if (aType == "Page")
+ preference.value = colorObj.BackgroundColor;
+ else
+ preference.value = colorObj.TextColor;
+}
+
+function UpdateDependent(aCustomEnabled)
+{
+ ToggleElements(aCustomEnabled);
+
+ if (aCustomEnabled)
+ { // Set current editor colors on preview and buttons
+ SetColors("textCW", "normalText", document.getElementById("editor.text_color").value);
+ SetColors("linkCW", "linkText", document.getElementById("editor.link_color").value);
+ SetColors("activeCW", "activeLinkText", document.getElementById("editor.active_link_color").value);
+ SetColors("visitedCW", "visitedLinkText", document.getElementById("editor.followed_link_color").value);
+ SetColors("backgroundCW", "ColorPreview", document.getElementById("editor.background_color").value);
+ }
+ else
+ { // Set current browser colors on preview
+ SetBgAndFgColors(gPrefService.getBoolPref("browser.display.use_system_colors"));
+ SetColorPreview("linkText", gPrefService.getCharPref("browser.anchor_color"));
+ SetColorPreview("activeLinkText", gPrefService.getCharPref("browser.active_color"));
+ SetColorPreview("visitedLinkText", gPrefService.getCharPref("browser.visited_color"));
+ }
+}
+
+function ToggleElements(aCustomEnabled)
+{
+ var buttons = document.getElementById("color-rows").getElementsByTagName("button");
+
+ for (var i = 0; i < buttons.length; i++)
+ {
+ let isLocked = CheckLocked(buttons[i].id);
+ buttons[i].disabled = !aCustomEnabled || isLocked;
+ buttons[i].previousSibling.disabled = !aCustomEnabled || isLocked;
+ buttons[i].firstChild.setAttribute("default", !aCustomEnabled || isLocked);
+ }
+}
+
+function CheckLocked(aButtonID)
+{
+ return document.getElementById("editor." + aButtonID + "_color").locked;
+}
+
+// Updates preview and button color when a editor color pref change
+function UpdateColors(aColorWellID, aPreviewID, aColor)
+{
+ // Only show editor colors from prefs if we're in custom mode
+ if (!document.getElementById("editor.use_custom_colors").value)
+ return;
+
+ SetColors(aColorWellID, aPreviewID, aColor)
+}
+
+function SetColors(aColorWellID, aPreviewID, aColor)
+{
+ SetColorWell(aColorWellID, aColor);
+ SetColorPreview(aPreviewID, aColor);
+}
+
+function SetColorWell(aColorWellID, aColor)
+{
+ document.getElementById(aColorWellID).style.backgroundColor = aColor;
+}
+
+function SetColorPreview(aPreviewID, aColor)
+{
+ if (aPreviewID == "ColorPreview")
+ document.getElementById(aPreviewID).style.backgroundColor = aColor;
+ else
+ document.getElementById(aPreviewID).style.color = aColor;
+}
+
+function UpdateBgImagePreview(aImage)
+{
+ var colorPreview = document.getElementById("ColorPreview");
+ colorPreview.style.backgroundImage = aImage && "url(" + aImage + ")";
+}
+
+// Sets browser background/foreground colors
+function SetBgAndFgColors(aSysPrefEnabled)
+{
+ if (aSysPrefEnabled)
+ { // Use system colors
+ SetColorPreview("normalText", "windowtext");
+ SetColorPreview("ColorPreview", "window");
+ }
+ else
+ {
+ SetColorPreview("normalText", gPrefService.getCharPref("browser.display.foreground_color"));
+ SetColorPreview("ColorPreview", gPrefService.getCharPref("browser.display.background_color"));
+ }
+}
+
+function ChooseImageFile()
+{
+ const nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+ var editorBundle = document.getElementById("bundle_editor");
+ var title = editorBundle.getString("SelectImageFile");
+ fp.init(window, title, nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterImages);
+ if (fp.show() == nsIFilePicker.returnOK)
+ document.getElementById("editor.default_background_image").value = fp.fileURL.spec;
+
+ var textbox = document.getElementById("backgroundImageInput");
+ textbox.focus();
+ textbox.select();
+}
+
+function WindowOnUnload()
+{
+ gPrefService.removeObserver("browser.display.use_system_colors", browserPrefsObserver, false);
+ gPrefService.removeObserver("browser.display.foreground_color", browserPrefsObserver, false);
+ gPrefService.removeObserver("browser.display.background_color", browserPrefsObserver, false);
+ gPrefService.removeObserver("browser.anchor_color", browserPrefsObserver, false);
+ gPrefService.removeObserver("browser.active_color", browserPrefsObserver, false);
+ gPrefService.removeObserver("browser.visited_color", browserPrefsObserver, false);
+ window.removeEventListener("unload", WindowOnUnload, false);
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/pref-composer.xul
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 1998-2000
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ Ryan Cassin (rcassin@supernova.org)
+
+ Alternatively, the contents of this file may be used under the terms of
+ either of the GNU General Public License Version 2 or later (the "GPL"),
+ or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/pref-composer.dtd">
+
+<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <prefpane id="composer_pane" label="&pref.composer.title;">
+
+ <preferences id="composer_preferences">
+ <preference id="editor.history.url_maximum"
+ name="editor.history.url_maximum"
+ type="int"/>
+ <preference id="editor.prettyprint"
+ name="editor.prettyprint"
+ type="bool"
+ inverted="true"/>
+ <preference id="editor.save_associated_files"
+ name="editor.save_associated_files"
+ type="bool"/>
+ <preference id="editor.always_show_publish_dialog"
+ name="editor.always_show_publish_dialog"
+ type="bool"/>
+ <preference id="editor.table.maintain_structure"
+ name="editor.table.maintain_structure"
+ type="bool"/>
+ <preference id="editor.use_css"
+ name="editor.use_css"
+ type="bool"/>
+ <preference id="editor.CR_creates_new_p"
+ name="editor.CR_creates_new_p"
+ type="bool"/>
+ </preferences>
+
+ <!-- Recent files menu -->
+ <groupbox>
+ <caption label="&recentFiles.title;"/>
+ <hbox align="center">
+ <label value="&documentsInMenu.label;"
+ accesskey="&documentsInMenu.accesskey;"
+ control="recentFiles"/>
+ <textbox id="recentFiles"
+ name="recent string"
+ type="number"
+ max="99"
+ min="0"
+ maxlength="2"
+ size="3"
+ value="10"
+ preference="editor.history.url_maximum"/>
+ </hbox>
+ </groupbox>
+
+ <!-- HTML formatting on output -->
+ <groupbox>
+ <caption label="&savingFiles.title;"/>
+ <checkbox id="preserveFormatting"
+ label="&preserveExisting.label;"
+ accesskey="&preserveExisting.accesskey;"
+ tooltiptext="&preserveExisting.tooltip;"
+ preference="editor.prettyprint"/>
+ <checkbox id="saveAssociatedFiles"
+ label="&saveAssociatedFiles.label;"
+ accesskey="&saveAssociatedFiles.accesskey;"
+ preference="editor.save_associated_files"/>
+ <checkbox id="showPublishDialog"
+ label="&showPublishDialog.label;"
+ accesskey="&showPublishDialog.accesskey;"
+ preference="editor.always_show_publish_dialog"/>
+ </groupbox>
+
+ <groupbox align="start">
+ <caption label="&composerEditing.label;"/>
+ <checkbox id="maintainTableStructure"
+ label="&maintainStructure.label;"
+ accesskey="&maintainStructure.accesskey;"
+ tooltiptext="&maintainStructure.tooltip;"
+ preference="editor.table.maintain_structure"/>
+ <checkbox id="useCSS"
+ label="&useCSS.label;"
+ accesskey="&useCSS.accesskey;"
+ preference="editor.use_css"/>
+ <checkbox id="crInPCreatesNewP"
+ label="&crInPCreatesNewP.label;"
+ accesskey="&crInPCreatesNewP.accesskey;"
+ preference="editor.CR_creates_new_p"/>
+ </groupbox>
+ </prefpane>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/pref-editing.xul
@@ -0,0 +1,215 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 1998-2000
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+
+ Alternatively, the contents of this file may be used under the terms of
+ either of the GNU General Public License Version 2 or later (the "GPL"),
+ or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/pref-editing.dtd">
+
+<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <prefpane id="editing_pane"
+ label="&pref.editing.title;"
+ script="chrome://editor/content/pref-composer.js">
+
+ <preferences id="editing_preferences">
+ <preference id="editor.author"
+ name="editor.author"
+ type="string"/>
+ <preference id="editor.use_custom_colors"
+ name="editor.use_custom_colors"
+ type="bool"
+ onchange="UpdateDependent(this.value);"/>
+ <preference id="editor.text_color"
+ name="editor.text_color"
+ type="string"
+ onchange="UpdateColors('textCW', 'normalText', this.value);"/>
+ <preference id="editor.link_color"
+ name="editor.link_color"
+ type="string"
+ onchange="UpdateColors('linkCW', 'linkText', this.value);"/>
+ <preference id="editor.active_link_color"
+ name="editor.active_link_color"
+ type="string"
+ onchange="UpdateColors('activeCW', 'activeLinkText', this.value);"/>
+ <preference id="editor.followed_link_color"
+ name="editor.followed_link_color"
+ type="string"
+ onchange="UpdateColors('visitedCW', 'visitedLinkText', this.value);"/>
+ <preference id="editor.background_color"
+ name="editor.background_color"
+ type="string"
+ onchange="UpdateColors('backgroundCW', 'ColorPreview', this.value);"/>
+ <preference id="editor.default_background_image"
+ name="editor.default_background_image"
+ type="string"
+ onchange="UpdateBgImagePreview(this.value);"/>
+ </preferences>
+
+ <stringbundle id="bundle_editor"
+ src="chrome://editor/locale/editor.properties"/>
+
+ <vbox>
+ <label value="&authorName.label;"
+ accesskey="&authorName.accesskey;"
+ control="editorAuthor">
+ </label>
+ <hbox>
+ <textbox id="editorAuthor"
+ flex="1"
+ preference="editor.author"/>
+ <spacer flex="1"/>
+ </hbox>
+ </vbox>
+ <spacer class="smallspacer"/>
+ <groupbox align="start">
+ <caption label="&pageColorHeader;"/>
+ <radiogroup id="useCustomColors"
+ preference="editor.use_custom_colors">
+ <radio id="defaultColorsRadio"
+ value="false"
+ label="&defaultColorsRadio.label;"
+ accesskey="&defaultColors.accesskey;"/>
+ <radio id="customColorsRadio"
+ value="true"
+ label="&customColorsRadio.label;"
+ accesskey="&customColors.accesskey;"/>
+ </radiogroup>
+ <hbox class="indent">
+ <grid>
+ <columns><column/><column/></columns>
+ <rows id="color-rows">
+ <row align="center">
+ <label id="textLabel"
+ value="&normalText.label;&colon.character;"
+ accesskey="&normalText.accesskey;"
+ control="text"/>
+ <button id="text"
+ class="color-button"
+ oncommand="GetColorAndUpdatePref('Text', 'text');">
+ <spacer id="textCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="linkLabel"
+ value="&linkText.label;&colon.character;"
+ accesskey="&linkText.accesskey;"
+ control="link"/>
+ <button id="link"
+ class="color-button"
+ oncommand="GetColorAndUpdatePref('Link', 'link');">
+ <spacer id="linkCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="activeLinkLabel"
+ value="&activeLinkText.label;&colon.character;"
+ accesskey="&activeLinkText.accesskey;"
+ control="active_link"/>
+ <button id="active_link"
+ class="color-button"
+ oncommand="GetColorAndUpdatePref('ActiveLink', 'active_link');">
+ <spacer id="activeCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="visitedLinkLabel"
+ value ="&visitedLinkText.label;&colon.character;"
+ accesskey="&visitedLinkText.accesskey;"
+ control="followed_link"/>
+ <button id="followed_link"
+ class="color-button"
+ oncommand="GetColorAndUpdatePref('VisitedLink', 'followed_link');">
+ <spacer id="visitedCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="backgroundLabel"
+ value="&background.label;"
+ accesskey="&background.accesskey;"
+ control="background"/>
+ <button id="background"
+ class="color-button"
+ oncommand="GetColorAndUpdatePref('Page', 'background');">
+ <spacer id="backgroundCW" class="color-well"/>
+ </button>
+ </row>
+ </rows>
+ </grid>
+ <vbox id="ColorPreview"
+ flex="1">
+ <spacer flex="1"/>
+ <label id="normalText"
+ class="larger"
+ value="&normalText.label;"/>
+ <spacer flex="1"/>
+ <label id="linkText"
+ class="larger"
+ value="&linkText.label;"/>
+ <spacer flex="1"/>
+ <label id="activeLinkText"
+ class="larger"
+ value="&activeLinkText.label;"/>
+ <spacer flex="1"/>
+ <label id="visitedLinkText"
+ class="larger"
+ value="&visitedLinkText.label;"/>
+ <spacer flex="1"/>
+ </vbox>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <label id="backgroundImageLabel"
+ value="&backgroundImage.label;"
+ accesskey="&backgroundImage.accesskey;"
+ control="backgroundImageInput">
+ </label>
+ <hbox align="center">
+ <textbox id="backgroundImageInput"
+ class="uri-element"
+ preference="editor.default_background_image"
+ style="min-width: 23em;"
+ flex="1"/>
+ <button label="&chooseFile.label;"
+ accesskey="&chooseFile.accesskey;"
+ oncommand="ChooseImageFile();">
+ <observes element="backgroundImageInput" attribute="disabled"/>
+ </button>
+ </hbox>
+ </groupbox>
+ </prefpane>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/pref-toolbars.xul
@@ -0,0 +1,231 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Toolbar Preferences.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/pref-toolbars.dtd">
+
+<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <prefpane id="toolbars_pane"
+ label="&pref.toolbars.title;">
+
+ <preferences id="toolbars_preferences">
+ <preference id="editor.toolbars.showbutton.new"
+ name="editor.toolbars.showbutton.new"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.open"
+ name="editor.toolbars.showbutton.open"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.save"
+ name="editor.toolbars.showbutton.save"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.publish"
+ name="editor.toolbars.showbutton.publish"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.preview"
+ name="editor.toolbars.showbutton.preview"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.cut"
+ name="editor.toolbars.showbutton.cut"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.copy"
+ name="editor.toolbars.showbutton.copy"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.paste"
+ name="editor.toolbars.showbutton.paste"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.print"
+ name="editor.toolbars.showbutton.print"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.find"
+ name="editor.toolbars.showbutton.find"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.image"
+ name="editor.toolbars.showbutton.image"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.hline"
+ name="editor.toolbars.showbutton.hline"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.table"
+ name="editor.toolbars.showbutton.table"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.link"
+ name="editor.toolbars.showbutton.link"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.namedAnchor"
+ name="editor.toolbars.showbutton.namedAnchor"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.DecreaseFontSize"
+ name="editor.toolbars.showbutton.DecreaseFontSize"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.IncreaseFontSize"
+ name="editor.toolbars.showbutton.IncreaseFontSize"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.bold"
+ name="editor.toolbars.showbutton.bold"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.absolutePosition"
+ name="editor.toolbars.showbutton.absolutePosition"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.ul"
+ name="editor.toolbars.showbutton.ul"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.ol"
+ name="editor.toolbars.showbutton.ol"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.italic"
+ name="editor.toolbars.showbutton.italic"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.decreaseZIndex"
+ name="editor.toolbars.showbutton.decreaseZIndex"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.outdent"
+ name="editor.toolbars.showbutton.outdent"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.indent"
+ name="editor.toolbars.showbutton.indent"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.underline"
+ name="editor.toolbars.showbutton.underline"
+ type="bool"/>
+ <preference id="editor.toolbars.showbutton.increaseZIndex"
+ name="editor.toolbars.showbutton.increaseZIndex"
+ type="bool"/>
+ </preferences>
+
+ <groupbox orient="horizontal">
+ <caption label="&composition.caption;"/>
+ <vbox flex="1">
+ <checkbox id="showNew"
+ label="&new.label;"
+ preference="editor.toolbars.showbutton.new"/>
+ <checkbox id="showOpen"
+ label="&open.label;"
+ preference="editor.toolbars.showbutton.open"/>
+ <checkbox id="showSave"
+ label="&save.label;"
+ preference="editor.toolbars.showbutton.save"/>
+ <checkbox id="showPublish"
+ label="&publish.label;"
+ preference="editor.toolbars.showbutton.publish"/>
+ <checkbox id="showPreview"
+ label="&preview.label;"
+ preference="editor.toolbars.showbutton.preview"/>
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="showCut"
+ label="&cut.label;"
+ preference="editor.toolbars.showbutton.cut"/>
+ <checkbox id="showCopy"
+ label="©.label;"
+ preference="editor.toolbars.showbutton.copy"/>
+ <checkbox id="showPaste"
+ label="&paste.label;"
+ preference="editor.toolbars.showbutton.paste"/>
+ <checkbox id="showPrint"
+ label="&print.label;"
+ preference="editor.toolbars.showbutton.print"/>
+ <checkbox id="showFind"
+ label="&find.label;"
+ preference="editor.toolbars.showbutton.find"/>
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="showImage"
+ label="&image.label;"
+ preference="editor.toolbars.showbutton.image"/>
+ <checkbox id="showHline"
+ label="&hline.label;"
+ preference="editor.toolbars.showbutton.hline"/>
+ <checkbox id="showTable"
+ label="&table.label;"
+ preference="editor.toolbars.showbutton.table"/>
+ <checkbox id="showLink"
+ label="&link.label;"
+ preference="editor.toolbars.showbutton.link"/>
+ <checkbox id="showAnchor"
+ label="&anchor.label;"
+ preference="editor.toolbars.showbutton.namedAnchor"/>
+ </vbox>
+ </groupbox>
+
+ <groupbox orient="horizontal">
+ <caption label="&formatting.caption;"/>
+ <vbox flex="1">
+ <checkbox id="showSmaller"
+ label="&smaller.label;"
+ preference="editor.toolbars.showbutton.DecreaseFontSize"/>
+ <checkbox id="showLarger"
+ label="&larger.label;"
+ preference="editor.toolbars.showbutton.IncreaseFontSize"/>
+ <checkbox id="showBold"
+ label="&bold.label;"
+ preference="editor.toolbars.showbutton.bold"/>
+ <checkbox id="showAbsolutePosition"
+ label="&absolutePosition.label;"
+ preference="editor.toolbars.showbutton.absolutePosition"/>
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="showBullets"
+ label="&bullets.label;"
+ preference="editor.toolbars.showbutton.ul"/>
+ <checkbox id="showNumbers"
+ label="&numbers.label;"
+ preference="editor.toolbars.showbutton.ol"/>
+ <checkbox id="showItalic"
+ label="&italic.label;"
+ preference="editor.toolbars.showbutton.italic"/>
+ <checkbox id="showDecreaseZIndex"
+ label="&decreaseZIndex.label;"
+ preference="editor.toolbars.showbutton.decreaseZIndex"/>
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="showOutdent"
+ label="&outdent.label;"
+ preference="editor.toolbars.showbutton.outdent"/>
+ <checkbox id="showIndent"
+ label="&indent.label;"
+ preference="editor.toolbars.showbutton.indent"/>
+ <checkbox id="showUnderline"
+ label="&underline.label;"
+ preference="editor.toolbars.showbutton.underline"/>
+ <checkbox id="showIncreaseZIndex"
+ label="&increaseZIndex.label;"
+ preference="editor.toolbars.showbutton.increaseZIndex"/>
+ </vbox>
+ </groupbox>
+ </prefpane>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/composer/content/publishprefs.js
@@ -0,0 +1,951 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * cmanske@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/****************** Get publishing data methods *******************/
+
+// Build an array of all publish site data obtained from prefs
+function GetPublishSiteData()
+{
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return null;
+
+ // Array of site names - sorted, but don't put default name first
+ var siteNameList = GetSiteNameList(true, false);
+ if (!siteNameList)
+ return null;
+
+ // Array of all site data
+ var siteArray = [];
+
+ // We rewrite siteName prefs to eliminate names if data is bad
+ // and to be sure order is the same as sorted name list
+ try {
+ publishBranch.deleteBranch("site_name.");
+ } catch (e) {}
+
+ // Get publish data using siteName as the key
+ var index = 0;
+ for (var i = 0; i < siteNameList.length; i++)
+ {
+ // Associated data uses site name as key
+ var publishData = GetPublishData_internal(publishBranch, siteNameList[i]);
+ if (publishData)
+ {
+ siteArray[index] = publishData;
+ SetPublishStringPref(publishBranch, "site_name."+index, siteNameList[i]);
+ index++;
+ }
+ else
+ {
+ try {
+ // Remove bad site prefs now
+ publishBranch.deleteBranch("site_data." + siteNameList[i] + ".");
+ } catch (e) {}
+ }
+ }
+
+ SavePrefFile();
+
+ if (index == 0) // No Valid pref records found!
+ return null;
+
+
+ return siteArray;
+}
+
+function GetDefaultPublishSiteName()
+{
+ var publishBranch = GetPublishPrefsBranch();
+ var name = "";
+ if (publishBranch)
+ name = GetPublishStringPref(publishBranch, "default_site");
+
+ return name;
+}
+
+// Return object with all info needed to publish
+// from database of sites previously published to.
+function CreatePublishDataFromUrl(docUrl)
+{
+ if (!docUrl || IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file")
+ return null;
+
+ var pubSiteData = GetPublishSiteData();
+ if (pubSiteData)
+ {
+ var dirObj = {};
+ var index = FindSiteIndexAndDocDir(pubSiteData, docUrl, dirObj);
+ var publishData;
+ if (index != -1)
+ {
+ publishData = pubSiteData[index];
+ publishData.docDir = FormatDirForPublishing(dirObj.value)
+
+ //XXX Problem: OtherDir: How do we decide when to use the dir in
+ // publishSiteData (default DocDir) or docDir from current filepath?
+ publishData.otherDir = FormatDirForPublishing(pubSiteData[index].otherDir);
+
+ publishData.filename = GetFilename(docUrl);
+ publishData.notInSiteData = false;
+ return publishData;
+ }
+ }
+
+ // Document wasn't found in publish site database
+ // Create data just from URL
+
+ // Extract username and password from docUrl
+ var userObj = {};
+ var passObj = {};
+ var pubUrl = StripUsernamePassword(docUrl, userObj, passObj);
+
+ // Strip off filename
+ var lastSlash = pubUrl.lastIndexOf("\/");
+ //XXX Look for "?", "=", and "&" ?
+ pubUrl = pubUrl.slice(0, lastSlash+1);
+
+ var siteName = CreateSiteNameFromUrl(pubUrl, pubSiteData);
+
+ publishData = {
+ siteName : siteName,
+ previousSiteName : siteName,
+ filename : GetFilename(docUrl),
+ username : userObj.value,
+ password : passObj.value,
+ savePassword : false,
+ publishUrl : pubUrl,
+ browseUrl : pubUrl,
+ docDir : "",
+ otherDir : "",
+ publishOtherFiles : true,
+ dirList : [""],
+ saveDirs : false,
+ notInSiteData : true
+ }
+
+ return publishData;
+}
+
+function CreateSiteNameFromUrl(url, publishSiteData)
+{
+ var host = GetHost(url);
+ var schemePostfix = " (" + GetScheme(url) + ")";
+ var siteName = host + schemePostfix;
+
+ if (publishSiteData)
+ {
+ // Look for duplicates. Append "-1" etc until unique name found
+ var i = 1;
+ var exists = false;
+ do {
+ exists = PublishSiteNameExists(siteName, publishSiteData, -1)
+ if (exists)
+ siteName = host + "-" + i + schemePostfix;
+ i++;
+ }
+ while (exists);
+ }
+ return siteName;
+}
+
+// Similar to above, but in param is a site profile name
+// Note that this is more efficient than getting from a URL,
+// since we don't have to get all the sitedata but can key off of sitename.
+// Caller must supply the current docUrl or just a filename
+// If doc URL is supplied, we find the publish subdirectory if publishUrl is part of docUrl
+function GetPublishDataFromSiteName(siteName, docUrlOrFilename)
+{
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return null;
+
+ var siteNameList = GetSiteNameList(false, false);
+ if (!siteNameList)
+ return null;
+ for (var i = 0; i < siteNameList.length; i++)
+ {
+ if (siteNameList[i] == siteName)
+ {
+ var publishData = GetPublishData_internal(publishBranch, siteName);
+ if (GetScheme(docUrlOrFilename))
+ FillInMatchingPublishData(publishData, docUrlOrFilename);
+ else
+ publishData.filename = docUrlOrFilename;
+
+ return publishData;
+ }
+ }
+ return null;
+}
+
+function GetDefaultPublishData()
+{
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return null;
+
+ var siteName = GetPublishStringPref(publishBranch, "default_site");
+ if (!siteName)
+ return null;
+
+ return GetPublishData_internal(publishBranch, siteName);
+}
+
+function GetPublishData_internal(publishBranch, siteName)
+{
+ if (!publishBranch || !siteName)
+ return null;
+
+ var prefPrefix = "site_data." + siteName + ".";
+
+ // We must have a publish url, else we ignore this site
+ // (siteData and siteNames for sites with incomplete data
+ // will get deleted by SavePublishSiteDataToPrefs)
+ var publishUrl = GetPublishStringPref(publishBranch, prefPrefix+"url");
+ if (!publishUrl)
+ return null;
+
+ var savePassword = false;
+ var publishOtherFiles = true;
+ try {
+ savePassword = publishBranch.getBoolPref(prefPrefix+"save_password");
+ publishOtherFiles = publishBranch.getBoolPref(prefPrefix+"publish_other_files");
+ } catch (e) {}
+
+ var publishData = {
+ siteName : siteName,
+ previousSiteName : siteName,
+ filename : "",
+ username : GetPublishStringPref(publishBranch, prefPrefix+"username"),
+ savePassword : savePassword,
+ publishUrl : publishUrl,
+ browseUrl : GetPublishStringPref(publishBranch, prefPrefix+"browse_url"),
+ docDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"doc_dir")),
+ otherDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"other_dir")),
+ publishOtherFiles : publishOtherFiles,
+ saveDirs : false
+ }
+
+ // Get password from PasswordManager
+ publishData.password = GetSavedPassword(publishData);
+
+ // If password was found, user must have checked "Save password"
+ // checkbox in prompt outside of publishing, so override the pref we stored
+ if (publishData.password)
+ {
+ if (!savePassword)
+ {
+ try {
+ publishPrefsBranch.setBoolPref(prefPrefix+"save_password", true);
+ } catch (e) {}
+ }
+ publishData.savePassword = true;
+ }
+
+ // Build history list of directories
+ // Always supply the root dir
+ publishData.dirList = [""];
+
+ // Get the rest from prefs
+ var dirCount = {value:0};
+ var dirPrefs;
+ try {
+ dirPrefs = publishBranch.getChildList(prefPrefix+"dir.", dirCount);
+ } catch (e) {}
+
+ if (dirPrefs && dirCount.value > 0)
+ {
+ if (dirCount.value > 1)
+ dirPrefs.sort();
+
+ for (var j = 0; j < dirCount.value; j++)
+ {
+ var dirName = GetPublishStringPref(publishBranch, dirPrefs[j]);
+ if (dirName)
+ publishData.dirList[j+1] = dirName;
+ }
+ }
+
+ return publishData;
+}
+
+/****************** Save publishing data methods *********************/
+
+// Save the siteArray containing all current publish site data
+function SavePublishSiteDataToPrefs(siteArray, defaultName)
+{
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return false;
+
+ try {
+ if (siteArray)
+ {
+ var defaultFound = false;
+
+ // Clear existing names and data -- rebuild all site prefs
+ publishBranch.deleteBranch("site_name.");
+ publishBranch.deleteBranch("site_data.");
+
+ for (var i = 0; i < siteArray.length; i++)
+ {
+ SavePublishData_Internal(publishBranch, siteArray[i], i);
+ if (!defaultFound)
+ defaultFound = defaultName == siteArray[i].siteName;
+ }
+ // Assure that we have a default name
+ if (siteArray.length && !defaultFound)
+ defaultName = siteArray[0].siteName;
+ }
+
+ // Save default site name
+ SetPublishStringPref(publishBranch, "default_site", defaultName);
+
+ // Force saving to file so next page edited finds these values
+ SavePrefFile();
+ }
+ catch (ex) { return false; }
+
+ return true;
+}
+
+// Update prefs if publish site already exists
+// or add prefs for a new site
+function SavePublishDataToPrefs(publishData)
+{
+ if (!publishData || !publishData.publishUrl)
+ return false;
+
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return false;
+
+ // Create name from URL if no site name is provided
+ if (!publishData.siteName)
+ publishData.siteName = CreateSiteNameFromUrl(publishData.publishUrl, publishData);
+
+ var siteCount = {value:0};
+ var siteNamePrefs;
+ try {
+ siteNamePrefs = publishBranch.getChildList("site_name.", siteCount);
+ } catch (e) {}
+
+ if (!siteNamePrefs || siteCount.value == 0)
+ {
+ // We currently have no site prefs, so create them
+ var siteData = [publishData];
+ return SavePublishSiteDataToPrefs(siteData, publishData.siteName);
+ }
+
+ // Use "previous" name if available in case it was changed
+ var previousSiteName = ("previousSiteName" in publishData && publishData.previousSiteName) ?
+ publishData.previousSiteName : publishData.siteName;
+
+ // Find site number of existing site or fall through at next available one
+ // (Number is arbitrary; needed to construct unique "site_name.x" pref string)
+ for (var i = 0; i < siteCount.value; i++)
+ {
+ var siteName = GetPublishStringPref(publishBranch, "site_name."+i);
+
+ if (siteName == previousSiteName)
+ {
+ // Delete prefs for an existing site
+ try {
+ publishBranch.deleteBranch("site_data." + siteName + ".");
+ } catch (e) {}
+ break;
+ }
+ }
+
+ // We've taken care of finding old duplicate, so be sure 'previous name' is current
+ publishData.previousSiteName = publishData.siteName;
+
+ var ret = SavePublishData_Internal(publishBranch, publishData, i);
+ if (ret)
+ {
+ // Check if siteName was the default and we need to update that
+ var defaultSiteName = GetPublishStringPref(publishBranch, "default_site");
+ if (previousSiteName == defaultSiteName
+ && publishData.siteName != defaultSiteName)
+ SetPublishStringPref(publishBranch, "default_site", publishData.siteName);
+
+ SavePrefFile();
+
+ // Clear signal to save these data
+ if ("notInSiteData" in publishData && publishData.notInSiteData)
+ publishData.notInSiteData = false;
+ }
+ return ret;
+}
+
+// Save data at a particular site number
+function SavePublishData_Internal(publishPrefsBranch, publishData, siteIndex)
+{
+ if (!publishPrefsBranch || !publishData)
+ return false;
+
+ SetPublishStringPref(publishPrefsBranch, "site_name."+siteIndex, publishData.siteName);
+
+ FixupUsernamePasswordInPublishData(publishData);
+
+ var prefPrefix = "site_data." + publishData.siteName + "."
+
+ SetPublishStringPref(publishPrefsBranch, prefPrefix+"url", publishData.publishUrl);
+ SetPublishStringPref(publishPrefsBranch, prefPrefix+"browse_url", publishData.browseUrl);
+ SetPublishStringPref(publishPrefsBranch, prefPrefix+"username", publishData.username);
+
+ try {
+ publishPrefsBranch.setBoolPref(prefPrefix+"save_password", publishData.savePassword);
+ publishPrefsBranch.setBoolPref(prefPrefix+"publish_other_files", publishData.publishOtherFiles);
+ } catch (e) {}
+
+ // Save password using PasswordManager
+ // (If publishData.savePassword = false, this clears existing password)
+ SavePassword(publishData);
+
+ SetPublishStringPref(publishPrefsBranch, prefPrefix+"doc_dir",
+ FormatDirForPublishing(publishData.docDir));
+
+ if (publishData.publishOtherFiles && publishData.otherDir)
+ SetPublishStringPref(publishPrefsBranch, prefPrefix+"other_dir",
+ FormatDirForPublishing(publishData.otherDir));
+
+ if ("saveDirs" in publishData && publishData.saveDirs)
+ {
+ if (publishData.docDir)
+ AppendNewDirToList(publishData, publishData.docDir);
+
+ if (publishData.publishOtherFiles && publishData.otherDir
+ && publishData.otherDir != publishData.docDir)
+ AppendNewDirToList(publishData, publishData.otherDir);
+ }
+
+ // Save array of subdirectories with site
+ if (publishData.dirList.length)
+ {
+ publishData.dirList.sort();
+ var dirIndex = 0;
+ for (var j = 0; j < publishData.dirList.length; j++)
+ {
+ var dir = publishData.dirList[j];
+
+ // Don't store the root dir
+ if (dir && dir != "/")
+ {
+ SetPublishStringPref(publishPrefsBranch, prefPrefix + "dir." + dirIndex, dir);
+ dirIndex++;
+ }
+ }
+ }
+
+ return true;
+}
+
+function AppendNewDirToList(publishData, newDir)
+{
+ newDir = FormatDirForPublishing(newDir);
+ if (!publishData || !newDir)
+ return;
+
+ if (!publishData.dirList)
+ {
+ publishData.dirList = [newDir];
+ return;
+ }
+
+ // Check if already in the list
+ for (var i = 0; i < publishData.dirList.length; i++)
+ {
+ // Don't add if already in the list
+ if (newDir == publishData.dirList[i])
+ return;
+ }
+ // Add to end of list
+ publishData.dirList[publishData.dirList.length] = newDir;
+}
+
+function RemovePublishSubdirectoryFromPrefs(publishData, removeDir)
+{
+ removeDir = FormatDirForPublishing(removeDir);
+ if (!publishData || !publishData.siteName || !removeDir)
+ return false;
+
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return false;
+
+ var prefPrefix = "site_data." + publishData.siteName + ".";
+
+ // Remove dir from the default dir prefs
+ if (publishData.docDir == removeDir)
+ {
+ publishData.docDir = "";
+ SetPublishStringPref(publishBranch, prefPrefix+"doc_dir", "");
+ }
+
+ if (publishData.otherDir == removeDir)
+ {
+ publishData.otherDir = "";
+ SetPublishStringPref(publishBranch, prefPrefix+"other_dir", "");
+ }
+
+ prefPrefix += "dir.";
+
+ // Delete entire subdir list
+ try {
+ publishBranch.deleteBranch(prefPrefix);
+ } catch (e) {}
+
+ // Rebuild prefs, skipping over site to remove
+ if (publishData.dirList.length)
+ {
+ var dirIndex = 0;
+ var docDirInList = false;
+ var otherDirInList = false;
+ for (var i = 0; i < publishData.dirList.length; i++)
+ {
+ var dir = publishData.dirList[i];
+ if (dir == removeDir)
+ {
+ // Remove item from the dirList array
+ publishData.dirList.splice(i, 1);
+ --i;
+ }
+ else if (dir && dir != "/") // skip empty or root dir
+ {
+ // Save to prefs
+ SetPublishStringPref(publishBranch, prefPrefix + dirIndex, dir);
+ dirIndex++;
+ }
+ }
+ }
+ SavePrefFile();
+ return true;
+}
+
+function SetDefaultSiteName(name)
+{
+ if (name)
+ {
+ var publishBranch = GetPublishPrefsBranch();
+ if (publishBranch)
+ SetPublishStringPref(publishBranch, "default_site", name);
+
+ SavePrefFile();
+ }
+}
+
+function SavePrefFile()
+{
+ try {
+ if (gPrefsService)
+ gPrefsService.savePrefFile(null);
+ }
+ catch (e) {}
+}
+
+/***************** Helper / utility methods ********************/
+
+function GetPublishPrefsBranch()
+{
+ var prefsService = GetPrefsService();
+ if (!prefsService)
+ return null;
+
+ return prefsService.getBranch("editor.publish.");
+}
+
+function GetSiteNameList(doSort, defaultFirst)
+{
+ var publishBranch = GetPublishPrefsBranch();
+ if (!publishBranch)
+ return null;
+
+ var siteCountObj = {value:0};
+ var siteNamePrefs;
+ try {
+ siteNamePrefs = publishBranch.getChildList("site_name.", siteCountObj);
+ } catch (e) {}
+
+ if (!siteNamePrefs || siteCountObj.value == 0)
+ return null;
+
+ // Array of site names
+ var siteNameList = [];
+ var index = 0;
+ var defaultName = "";
+ if (defaultFirst)
+ {
+ defaultName = GetPublishStringPref(publishBranch, "default_site");
+ // This always sorts to top -- replace with real string below
+ siteNameList[0] = "";
+ index++;
+ }
+
+ for (var i = 0; i < siteCountObj.value; i++)
+ {
+ var siteName = GetPublishStringPref(publishBranch, siteNamePrefs[i]);
+ // Skip if siteName pref is empty or is default name
+ if (siteName && siteName != defaultName)
+ {
+ siteNameList[index] = siteName;
+ index++;
+ }
+ }
+
+ if (siteNameList.length && doSort)
+ siteNameList.sort();
+
+ if (defaultName)
+ {
+ siteNameList[0] = defaultName;
+ index++;
+ }
+
+ return siteNameList.length? siteNameList : null;
+}
+
+function PublishSiteNameExists(name, publishSiteData, skipSiteIndex)
+{
+ if (!name)
+ return false;
+
+ if (!publishSiteData)
+ {
+ publishSiteData = GetPublishSiteData();
+ skipSiteIndex = -1;
+ }
+
+ if (!publishSiteData)
+ return false;
+
+ // Array of site names - sorted, but don't put default name first
+ for (var i = 0; i < publishSiteData.length; i++)
+ {
+ if (i != skipSiteIndex && name == publishSiteData[i].siteName)
+ return true;
+ }
+ return false;
+}
+
+// Find index of a site record in supplied publish site database
+// docUrl: Document URL with or without filename
+// (Must end in "/" if no filename)
+// dirObj.value = the directory of the document URL
+// relative to the base publishing URL, using "" if none
+//
+// XXX: Currently finds the site with the longest-matching url;
+// should we look for the shortest instead? Or match just the host portion?
+function FindSiteIndexAndDocDir(publishSiteData, docUrl, dirObj)
+{
+ if (dirObj)
+ dirObj.value = "";
+
+ if (!publishSiteData || !docUrl || GetScheme(docUrl) == "file")
+ return -1;
+
+ var siteIndex = -1;
+ var siteUrlLen = 0;
+
+ for (var i = 0; i < publishSiteData.length; i++)
+ {
+ // Site publish or browse url needs to be contained in document URL,
+ // but that may also have a directory after the site base URL
+ // So we must examine all records to find the site URL that best
+ // matches the document URL: the longest-matching substring (XXX is this right?)
+ var lenObj = {value:0};
+ var tempData = Clone(publishSiteData[i]);
+
+ // Check if this site matches docUrl (returns length of match if found)
+ var len = FillInMatchingPublishData(tempData, docUrl);
+
+ if (len > siteUrlLen)
+ {
+ siteIndex = i;
+ siteUrlLen = len;
+ if (dirObj)
+ dirObj.value = tempData.docDir;
+
+ // Continue to find the site with longest-matching publishUrl
+ }
+ }
+ return siteIndex;
+}
+
+// Look for a matching publish url within the document url
+// (We need to look at both "publishUrl" and "browseUrl" in case we are editing
+// an http: document but using ftp: to publish.)
+// If match is found:
+// Fill in the filename and subirectory based on the docUrl and
+// return the length of the docUrl with username+password stripped out
+function FillInMatchingPublishData(publishData, docUrl)
+{
+ if (!publishData || !docUrl)
+ return 0;
+
+ // Separate docUrl into the base url and filename
+ var lastSlash = docUrl.lastIndexOf("\/");
+ var baseUrl = docUrl.slice(0, lastSlash+1);
+ var filename = docUrl.slice(lastSlash+1);
+
+ // Strip username+password from docUrl because these
+ // are stored separately in publishData, never embedded in the publishUrl
+ // If both docUrl and publishData contain usernames,
+ // we must match that as well as the url
+ var username = {value:""};
+ baseUrl = StripUsernamePassword(baseUrl, username);
+ username = username.value;
+
+ var matchedLength = 0;
+ var pubUrlFound = publishData.publishUrl ?
+ baseUrl.indexOf(publishData.publishUrl) == 0 : false;
+ var browseUrlFound = publishData.browseUrl ?
+ baseUrl.indexOf(publishData.browseUrl) == 0 : false;
+
+ if ((pubUrlFound || browseUrlFound)
+ && (!username || !publishData.username || username == publishData.username))
+ {
+ // We found a match
+ matchedLength = pubUrlFound ? publishData.publishUrl.length
+ : publishData.browseUrl.length;
+
+ if (matchedLength > 0)
+ {
+ publishData.filename = filename;
+
+ // Subdirectory within the site is what's left in baseUrl after the matched portion
+ publishData.docDir = FormatDirForPublishing(baseUrl.slice(matchedLength));
+ }
+ }
+ return matchedLength;
+}
+
+// Prefs that don't exist will through an exception,
+// so just return an empty string
+function GetPublishStringPref(prefBranch, name)
+{
+ if (prefBranch && name)
+ {
+ try {
+ return prefBranch.getComplexValue(name, Components.interfaces.nsISupportsString).data;
+ } catch (e) {}
+ }
+ return "";
+}
+
+function SetPublishStringPref(prefBranch, name, value)
+{
+ if (prefBranch && name)
+ {
+ try {
+ var str = Components.classes["@mozilla.org/supports-string;1"]
+ .createInstance(Components.interfaces.nsISupportsString);
+ str.data = value;
+ prefBranch.setComplexValue(name, Components.interfaces.nsISupportsString, str);
+ } catch (e) {}
+ }
+}
+
+// Assure that a publishing URL ends in "/", "=", "&" or "?"
+// Username and password should always be extracted as separate fields
+// and are not allowed to remain embedded in publishing URL
+function FormatUrlForPublishing(url)
+{
+ url = TrimString(StripUsernamePassword(url));
+ if (url)
+ {
+ var lastChar = url.charAt(url.length-1);
+ if (lastChar != "/" && lastChar != "=" && lastChar != "&" && lastChar != "?")
+ return (url + "/");
+ }
+ return url;
+}
+
+// Username and password present in publish url are
+// extracted into the separate "username" and "password" fields
+// of the publishData object
+// Returns true if we did change the publishData
+function FixupUsernamePasswordInPublishData(publishData)
+{
+ var ret = false;
+ if (publishData && publishData.publishUrl)
+ {
+ var userObj = {value:""};
+ var passObj = {value:""};
+ publishData.publishUrl = FormatUrlForPublishing(StripUsernamePassword(publishData.publishUrl, userObj, passObj));
+ if (userObj.value)
+ {
+ publishData.username = userObj.value;
+ ret = true;
+ }
+ if (passObj.value)
+ {
+ publishData.password = passObj.value;
+ ret = true;
+ }
+ // While we're at it, be sure browse URL is proper format
+ publishData.browseUrl = FormatUrlForPublishing(publishData.browseUrl);
+ }
+ return ret;
+}
+
+// Assure that a publishing directory ends with "/" and does not begin with "/"
+// Input dir is assumed to be a subdirectory string, not a full URL or pathname
+function FormatDirForPublishing(dir)
+{
+ dir = TrimString(dir);
+
+ // The "//" case is an expected "typo" filter
+ // that simplifies code below!
+ if (!dir || dir == "/" || dir == "//")
+ return "";
+
+ // Remove leading "/"
+ if (dir.charAt(0) == "/")
+ dir = dir.slice(1);
+
+ // Append "/" at the end if necessary
+ var dirLen = dir.length;
+ var lastChar = dir.charAt(dirLen-1);
+ if (dirLen > 1 && lastChar != "/" && lastChar != "=" && lastChar != "&" && lastChar != "?")
+ return (dir + "/");
+
+ return dir;
+}
+
+
+var gPasswordManager;
+function GetPasswordManager()
+{
+ if (!gPasswordManager)
+ {
+ var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"].createInstance();
+ if (passwordManager)
+ gPasswordManager = passwordManager.QueryInterface(Components.interfaces.nsIPasswordManager);
+ }
+ return gPasswordManager;
+}
+
+var gPasswordManagerInternal;
+function GetPasswordManagerInternal()
+{
+ if (!gPasswordManagerInternal)
+ {
+ try {
+ gPasswordManagerInternal =
+ Components.classes["@mozilla.org/passwordmanager;1"].createInstance(
+ Components.interfaces.nsIPasswordManagerInternal);
+ } catch (e) {
+ }
+ }
+ return gPasswordManagerInternal;
+}
+
+function GetSavedPassword(publishData)
+{
+ if (!publishData)
+ return "";
+ var passwordManagerInternal = GetPasswordManagerInternal();
+ if (!passwordManagerInternal)
+ return "";
+
+ var host = {value:""};
+ var user = {value:""};
+ var password = {value:""};
+ var url = GetUrlForPasswordManager(publishData);
+
+ try {
+ passwordManagerInternal.findPasswordEntry
+ (url, publishData.username, "", host, user, password);
+ return password.value;
+ } catch (e) {}
+
+ return "";
+}
+
+function SavePassword(publishData)
+{
+ if (!publishData || !publishData.publishUrl || !publishData.username)
+ return false;
+
+ var passwordManager = GetPasswordManager();
+ if (passwordManager)
+ {
+ var url = GetUrlForPasswordManager(publishData);
+
+ // Remove existing entry
+ // (Note: there is no method to update a password for an existing entry)
+ try {
+ passwordManager.removeUser(url, publishData.username);
+ } catch (e) {}
+
+ // If SavePassword is true, add new password
+ if (publishData.savePassword)
+ {
+ try {
+ passwordManager.addUser(url, publishData.username, publishData.password);
+ } catch (e) {}
+ }
+ return true;
+ }
+ return false;
+}
+
+function GetUrlForPasswordManager(publishData)
+{
+ if (!publishData || !publishData.publishUrl)
+ return false;
+
+ var url;
+
+ // For FTP, we must embed the username into the url for a site address
+ // XXX Maybe we should we do this for HTTP as well???
+ if (publishData.username && GetScheme(publishData.publishUrl) == "ftp")
+ url = InsertUsernameIntoUrl(publishData.publishUrl, publishData.username);
+ else
+ url = publishData.publishUrl;
+
+ // Strip off terminal "/"
+ var len = url.length;
+ if (len && url.charAt(len-1) == "\/")
+ url = url.slice(0, len-1);
+
+ return url;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAEAttributes.js
@@ -0,0 +1,1845 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Beth Epperson
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// HTML Attributes object for "Name" menulist
+var gHTMLAttr = {};
+
+// JS Events Attributes object for "Name" menulist
+var gJSAttr = {};
+
+
+// Core HTML attribute values //
+// This is appended to Name menulist when "_core" is attribute name
+var gCoreHTMLAttr =
+[
+ "^id",
+ "class",
+ "title"
+];
+
+// Core event attribute values //
+// This is appended to all JS menulists
+// except those elements having "noJSEvents"
+// as a value in their gJSAttr array.
+var gCoreJSEvents =
+[
+ "onclick",
+ "ondblclick",
+ "onmousedown",
+ "onmouseup",
+ "onmouseover",
+ "onmousemove",
+ "onmouseout",
+ "-",
+ "onkeypress",
+ "onkeydown",
+ "onkeyup"
+];
+
+// Following are commonly-used strings
+
+// Alse accept: sRGB: #RRGGBB //
+var gHTMLColors =
+[
+ "Aqua",
+ "Black",
+ "Blue",
+ "Fuchsia",
+ "Gray",
+ "Green",
+ "Lime",
+ "Maroon",
+ "Navy",
+ "Olive",
+ "Purple",
+ "Red",
+ "Silver",
+ "Teal",
+ "White",
+ "Yellow"
+];
+
+var gHAlign =
+[
+ "left",
+ "center",
+ "right"
+];
+
+var gHAlignJustify =
+[
+ "left",
+ "center",
+ "right",
+ "justify"
+];
+
+var gHAlignTableContent =
+[
+ "left",
+ "center",
+ "right",
+ "justify",
+ "char"
+];
+
+var gVAlignTable =
+[
+ "top",
+ "middle",
+ "bottom",
+ "baseline"
+];
+
+var gTarget =
+[
+ "_blank",
+ "_self",
+ "_parent",
+ "_top"
+];
+
+// ================ HTML Attributes ================ //
+/* For each element, there is an array of attributes,
+ whose name is the element name,
+ used to fill the "Attribute Name" menulist.
+ For each of those attributes, if they have a specific
+ set of values, those are listed in an array named:
+ "elementName_attName".
+
+ In each values string, the following characters
+ are signal to do input filtering:
+ "#" Allow only integer values
+ "%" Allow integer values or a number ending in "%"
+ "+" Allow integer values and allow "+" or "-" as first character
+ "!" Allow only one character
+ "^" The first character can be only be A-Z, a-z, hyphen, underscore, colon or period
+ "$" is an attribute required by HTML DTD
+*/
+
+/*
+ Most elements have the "dir" attribute,
+ so we use this value array
+ for all elements instead of specifying
+ separately for each element
+*/
+gHTMLAttr.all_dir =
+[
+ "ltr",
+ "rtl"
+];
+
+
+gHTMLAttr.a =
+[
+ "charset",
+ "type",
+ "name",
+ "href",
+ "^hreflang",
+ "target",
+ "rel",
+ "rev",
+ "!accesskey",
+ "shape", // with imagemap //
+ "coords", // with imagemap //
+ "#tabindex",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.a_target = gTarget;
+
+gHTMLAttr.a_rel =
+[
+ "alternate",
+ "stylesheet",
+ "start",
+ "next",
+ "prev",
+ "contents",
+ "index",
+ "glossary",
+ "copyright",
+ "chapter",
+ "section",
+ "subsection",
+ "appendix",
+ "help",
+ "bookmark"
+];
+
+gHTMLAttr.a_rev =
+[
+ "alternate",
+ "stylesheet",
+ "start",
+ "next",
+ "prev",
+ "contents",
+ "index",
+ "glossary",
+ "copyright",
+ "chapter",
+ "section",
+ "subsection",
+ "appendix",
+ "help",
+ "bookmark"
+];
+
+gHTMLAttr.a_shape =
+[
+ "rect",
+ "circle",
+ "poly",
+ "default"
+];
+
+gHTMLAttr.abbr =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.acronym =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.address =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+// this is deprecated //
+gHTMLAttr.applet =
+[
+ "codebase",
+ "archive",
+ "code",
+ "object",
+ "alt",
+ "name",
+ "%$width",
+ "%$height",
+ "align",
+ "#hspace",
+ "#vspace",
+ "-",
+ "_core"
+];
+
+gHTMLAttr.applet_align =
+[
+ "top",
+ "middle",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.area =
+[
+ "shape",
+ "coords",
+ "href",
+ "nohref",
+ "target",
+ "$alt",
+ "#tabindex",
+ "!accesskey",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.area_target = gTarget;
+
+gHTMLAttr.area_shape =
+[
+ "rect",
+ "circle",
+ "poly",
+ "default"
+];
+
+gHTMLAttr.area_nohref =
+[
+ "nohref"
+];
+
+gHTMLAttr.b =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.base =
+[
+ "href",
+ "target"
+];
+
+gHTMLAttr.base_target = gTarget;
+
+// this is deprecated //
+gHTMLAttr.basefont =
+[
+ "^id",
+ "$size",
+ "color",
+ "face"
+];
+
+gHTMLAttr.basefont_color = gHTMLColors;
+
+gHTMLAttr.bdo =
+[
+ "_core",
+ "-",
+ "^lang",
+ "$dir"
+];
+
+gHTMLAttr.bdo_dir =
+[
+ "ltr",
+ "rtl"
+];
+
+gHTMLAttr.big =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.blockquote =
+[
+ "cite",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.body =
+[
+ "background",
+ "bgcolor",
+ "text",
+ "link",
+ "vlink",
+ "alink",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.body_bgcolor = gHTMLColors;
+
+gHTMLAttr.body_text = gHTMLColors;
+
+gHTMLAttr.body_link = gHTMLColors;
+
+gHTMLAttr.body_vlink = gHTMLColors;
+
+gHTMLAttr.body_alink = gHTMLColors;
+
+gHTMLAttr.br =
+[
+ "clear",
+ "-",
+ "_core"
+];
+
+gHTMLAttr.br_clear =
+[
+ "none",
+ "left",
+ "all",
+ "right"
+];
+
+gHTMLAttr.button =
+[
+ "name",
+ "value",
+ "$type",
+ "disabled",
+ "#tabindex",
+ "!accesskey",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.button_type =
+[
+ "submit",
+ "button",
+ "reset"
+];
+
+gHTMLAttr.button_disabled =
+[
+ "disabled"
+];
+
+gHTMLAttr.caption =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.caption_align =
+[
+ "top",
+ "bottom",
+ "left",
+ "right"
+];
+
+
+// this is deprecated //
+gHTMLAttr.center =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.cite =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.code =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.col =
+[
+ "#$span",
+ "%width",
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "char",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.col_span =
+[
+ "1" // default
+];
+
+gHTMLAttr.col_align = gHAlignTableContent;
+
+gHTMLAttr.col_valign =
+[
+ "top",
+ "middle",
+ "bottom",
+ "baseline"
+];
+
+
+gHTMLAttr.colgroup =
+[
+ "#$span",
+ "%width",
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.colgroup_span =
+[
+ "1" // default
+];
+
+gHTMLAttr.colgroup_align = gHAlignTableContent;
+
+gHTMLAttr.colgroup_valign =
+[
+ "top",
+ "middle",
+ "bottom",
+ "baseline"
+];
+
+gHTMLAttr.dd =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.del =
+[
+ "cite",
+ "datetime",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.dfn =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+// this is deprecated //
+gHTMLAttr.dir =
+[
+ "compact",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.dir_compact =
+[
+ "compact"
+];
+
+gHTMLAttr.div =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.div_align = gHAlignJustify;
+
+gHTMLAttr.dl =
+[
+ "compact",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.dl_compact =
+[
+ "compact"
+];
+
+
+gHTMLAttr.dt =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.em =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.fieldset =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+// this is deprecated //
+gHTMLAttr.font =
+[
+ "+size",
+ "color",
+ "face",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.font_color = gHTMLColors;
+
+gHTMLAttr.form =
+[
+ "$action",
+ "$method",
+ "enctype",
+ "accept",
+ "name",
+ "accept-charset",
+ "target",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.form_method =
+[
+ "get",
+ "post"
+];
+
+gHTMLAttr.form_enctype =
+[
+ "application/x-www-form-urlencoded"
+];
+
+gHTMLAttr.form_target = gTarget;
+
+gHTMLAttr.frame =
+[
+ "longdesc",
+ "name",
+ "src",
+ "#frameborder",
+ "#marginwidth",
+ "#marginheight",
+ "noresize",
+ "$scrolling"
+];
+
+gHTMLAttr.frame_frameborder =
+[
+ "1",
+ "0"
+];
+
+gHTMLAttr.frame_noresize =
+[
+ "noresize"
+];
+
+gHTMLAttr.frame_scrolling =
+[
+ "auto",
+ "yes",
+ "no"
+];
+
+
+gHTMLAttr.frameset =
+[
+ "rows",
+ "cols",
+ "-",
+ "_core"
+];
+
+gHTMLAttr.h1 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h1_align = gHAlignJustify;
+
+gHTMLAttr.h2 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h2_align = gHAlignJustify;
+
+gHTMLAttr.h3 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h3_align = gHAlignJustify;
+
+gHTMLAttr.h4 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h4_align = gHAlignJustify;
+
+
+gHTMLAttr.h5 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h5_align = gHAlignJustify;
+
+gHTMLAttr.h6 =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.h6_align = gHAlignJustify;
+
+gHTMLAttr.head =
+[
+ "profile",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.hr =
+[
+ "align",
+ "noshade",
+ "#size",
+ "%width",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.hr_align = gHAlign;
+
+gHTMLAttr.hr_noshade =
+[
+ "noshade"
+];
+
+
+gHTMLAttr.html =
+[
+ "version",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.i =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.iframe =
+[
+ "longdesc",
+ "name",
+ "src",
+ "$frameborder",
+ "marginwidth",
+ "marginheight",
+ "$scrolling",
+ "align",
+ "%height",
+ "%width",
+ "-",
+ "_core"
+];
+
+gHTMLAttr.iframe_frameborder =
+[
+ "1",
+ "0"
+];
+
+gHTMLAttr.iframe_scrolling =
+[
+ "auto",
+ "yes",
+ "no"
+];
+
+gHTMLAttr.iframe_align =
+[
+ "top",
+ "middle",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.img =
+[
+ "$src",
+ "$alt",
+ "longdesc",
+ "name",
+ "%height",
+ "%width",
+ "usemap",
+ "ismap",
+ "align",
+ "#border",
+ "#hspace",
+ "#vspace",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.img_ismap =
+[
+ "ismap"
+];
+
+gHTMLAttr.img_align =
+[
+ "top",
+ "middle",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.input =
+[
+ "$type",
+ "name",
+ "value",
+ "checked",
+ "disabled",
+ "readonly",
+ "#size",
+ "#maxlength",
+ "src",
+ "alt",
+ "usemap",
+ "ismap",
+ "#tabindex",
+ "!accesskey",
+ "accept",
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.input_type =
+[
+ "text",
+ "password",
+ "checkbox",
+ "radio",
+ "submit",
+ "reset",
+ "file",
+ "hidden",
+ "image",
+ "button"
+];
+
+gHTMLAttr.input_checked =
+[
+ "checked"
+];
+
+gHTMLAttr.input_disabled =
+[
+ "disabled"
+];
+
+gHTMLAttr.input_readonly =
+[
+ "readonly"
+];
+
+
+gHTMLAttr.input_ismap =
+[
+ "ismap"
+];
+
+
+gHTMLAttr.input_align =
+[
+ "top",
+ "middle",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.ins =
+[
+ "cite",
+ "datetime",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.isindex =
+[
+ "prompt",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.kbd =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.label =
+[
+ "for",
+ "!accesskey",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.legend =
+[
+ "!accesskey",
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.legend_align =
+[
+ "top",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.li =
+[
+ "type",
+ "#value",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.li_type =
+[
+ "disc",
+ "square",
+ "circle",
+ "-",
+ "1",
+ "a",
+ "A",
+ "i",
+ "I"
+];
+
+gHTMLAttr.link =
+[
+ "charset",
+ "href",
+ "^hreflang",
+ "type",
+ "rel",
+ "rev",
+ "media",
+ "target",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.link_target = gTarget;
+
+gHTMLAttr.link_rel =
+[
+ "alternate",
+ "stylesheet",
+ "start",
+ "next",
+ "prev",
+ "contents",
+ "index",
+ "glossary",
+ "copyright",
+ "chapter",
+ "section",
+ "subsection",
+ "appendix",
+ "help",
+ "bookmark"
+];
+
+gHTMLAttr.link_rev =
+[
+ "alternate",
+ "stylesheet",
+ "start",
+ "next",
+ "prev",
+ "contents",
+ "index",
+ "glossary",
+ "copyright",
+ "chapter",
+ "section",
+ "subsection",
+ "appendix",
+ "help",
+ "bookmark"
+];
+
+gHTMLAttr.map =
+[
+ "$name",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.menu =
+[
+ "compact",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.menu_compact =
+[
+ "compact"
+];
+
+gHTMLAttr.meta =
+[
+ "http-equiv",
+ "name",
+ "$content",
+ "scheme",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.noframes =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.noscript =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.object =
+[
+ "declare",
+ "classid",
+ "codebase",
+ "data",
+ "type",
+ "codetype",
+ "archive",
+ "standby",
+ "%height",
+ "%width",
+ "usemap",
+ "name",
+ "#tabindex",
+ "align",
+ "#border",
+ "#hspace",
+ "#vspace",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.object_declare =
+[
+ "declare"
+];
+
+gHTMLAttr.object_align =
+[
+ "top",
+ "middle",
+ "bottom",
+ "left",
+ "right"
+];
+
+gHTMLAttr.ol =
+[
+ "type",
+ "compact",
+ "#start",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.ol_type =
+[
+ "1",
+ "a",
+ "A",
+ "i",
+ "I"
+];
+
+gHTMLAttr.ol_compact =
+[
+ "compact"
+];
+
+
+gHTMLAttr.optgroup =
+[
+ "disabled",
+ "$label",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.optgroup_disabled =
+[
+ "disabled"
+];
+
+
+gHTMLAttr.option =
+[
+ "selected",
+ "disabled",
+ "label",
+ "value",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.option_selected =
+[
+ "selected"
+];
+
+gHTMLAttr.option_disabled =
+[
+ "disabled"
+];
+
+
+gHTMLAttr.p =
+[
+ "align",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.p_align = gHAlignJustify;
+
+gHTMLAttr.param =
+[
+ "^id",
+ "$name",
+ "value",
+ "$valuetype",
+ "type"
+];
+
+gHTMLAttr.param_valuetype =
+[
+ "data",
+ "ref",
+ "object"
+];
+
+
+gHTMLAttr.pre =
+[
+ "%width",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.q =
+[
+ "cite",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.s =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.samp =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.script =
+[
+ "charset",
+ "$type",
+ "language",
+ "src",
+ "defer"
+];
+
+gHTMLAttr.script_defer =
+[
+ "defer"
+];
+
+
+gHTMLAttr.select =
+[
+ "name",
+ "#size",
+ "multiple",
+ "disabled",
+ "#tabindex",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.select_multiple =
+[
+ "multiple"
+];
+
+gHTMLAttr.select_disabled =
+[
+ "disabled"
+];
+
+gHTMLAttr.small =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.span =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.strike =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.strong =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.style =
+[
+ "$type",
+ "media",
+ "title",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.sub =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.sup =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.table =
+[
+ "summary",
+ "%width",
+ "#border",
+ "frame",
+ "rules",
+ "#cellspacing",
+ "#cellpadding",
+ "align",
+ "bgcolor",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.table_frame =
+[
+ "void",
+ "above",
+ "below",
+ "hsides",
+ "lhs",
+ "rhs",
+ "vsides",
+ "box",
+ "border"
+];
+
+gHTMLAttr.table_rules =
+[
+ "none",
+ "groups",
+ "rows",
+ "cols",
+ "all"
+];
+
+// Note; This is alignment of the table,
+// not table contents, like all other table child elements
+gHTMLAttr.table_align = gHAlign;
+
+gHTMLAttr.table_bgcolor = gHTMLColors;
+
+gHTMLAttr.tbody =
+[
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.tbody_align = gHAlignTableContent;
+
+gHTMLAttr.tbody_valign = gVAlignTable;
+
+gHTMLAttr.td =
+[
+ "abbr",
+ "axis",
+ "headers",
+ "scope",
+ "$#rowspan",
+ "$#colspan",
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "nowrap",
+ "bgcolor",
+ "%width",
+ "%height",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.td_scope =
+[
+ "row",
+ "col",
+ "rowgroup",
+ "colgroup"
+];
+
+gHTMLAttr.td_rowspan =
+[
+ "1" // default
+];
+
+gHTMLAttr.td_colspan =
+[
+ "1" // default
+];
+
+gHTMLAttr.td_align = gHAlignTableContent;
+
+gHTMLAttr.td_valign = gVAlignTable;
+
+gHTMLAttr.td_nowrap =
+[
+ "nowrap"
+];
+
+gHTMLAttr.td_bgcolor = gHTMLColors;
+
+gHTMLAttr.textarea =
+[
+ "name",
+ "$#rows",
+ "$#cols",
+ "disabled",
+ "readonly",
+ "#tabindex",
+ "!accesskey",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.textarea_disabled =
+[
+ "disabled"
+];
+
+gHTMLAttr.textarea_readonly =
+[
+ "readonly"
+];
+
+
+gHTMLAttr.tfoot =
+[
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.tfoot_align = gHAlignTableContent;
+
+gHTMLAttr.tfoot_valign = gVAlignTable;
+
+gHTMLAttr.th =
+[
+ "abbr",
+ "axis",
+ "headers",
+ "scope",
+ "$#rowspan",
+ "$#colspan",
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "nowrap",
+ "bgcolor",
+ "%width",
+ "%height",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.th_scope =
+[
+ "row",
+ "col",
+ "rowgroup",
+ "colgroup"
+];
+
+gHTMLAttr.th_rowspan =
+[
+ "1" // default
+];
+
+gHTMLAttr.th_colspan =
+[
+ "1" // default
+];
+
+gHTMLAttr.th_align = gHAlignTableContent;
+
+gHTMLAttr.th_valign = gVAlignTable;
+
+gHTMLAttr.th_nowrap =
+[
+ "nowrap"
+];
+
+gHTMLAttr.th_bgcolor = gHTMLColors;
+
+gHTMLAttr.thead =
+[
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.thead_align = gHAlignTableContent;
+
+gHTMLAttr.thead_valign = gVAlignTable;
+
+gHTMLAttr.title =
+[
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.tr =
+[
+ "align",
+ "!char",
+ "#charoff",
+ "valign",
+ "bgcolor",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.tr_align = gHAlignTableContent;
+
+gHTMLAttr.tr_valign = gVAlignTable;
+
+gHTMLAttr.tr_bgcolor = gHTMLColors;
+
+gHTMLAttr.tt =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.u =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+gHTMLAttr.ul =
+[
+ "type",
+ "compact",
+ "-",
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+gHTMLAttr.ul_type =
+[
+ "disc",
+ "square",
+ "circle"
+];
+
+gHTMLAttr.ul_compact =
+[
+ "compact"
+];
+
+
+// Prefix with "_" since this is reserved (it's stripped out)
+gHTMLAttr._var =
+[
+ "_core",
+ "-",
+ "^lang",
+ "dir"
+];
+
+// ================ JS Attributes ================ //
+// These are element specif even handlers.
+/* Most all elements use gCoreJSEvents, so those
+ are assumed except for those listed here with "noEvents"
+*/
+
+gJSAttr.a =
+[
+ "onfocus",
+ "onblur"
+];
+
+gJSAttr.area =
+[
+ "onfocus",
+ "onblur"
+];
+
+gJSAttr.body =
+[
+ "onload",
+ "onupload"
+];
+
+gJSAttr.button =
+[
+ "onfocus",
+ "onblur"
+];
+
+gJSAttr.form =
+[
+ "onsubmit",
+ "onreset"
+];
+
+gJSAttr.frameset =
+[
+ "onload",
+ "onunload"
+];
+
+gJSAttr.input =
+[
+ "onfocus",
+ "onblur",
+ "onselect",
+ "onchange"
+];
+
+gJSAttr.label =
+[
+ "onfocus",
+ "onblur"
+];
+
+gJSAttr.select =
+[
+ "onfocus",
+ "onblur",
+ "onchange"
+];
+
+gJSAttr.textarea =
+[
+ "onfocus",
+ "onblur",
+ "onselect",
+ "onchange"
+];
+
+// Elements that don't have JSEvents:
+gJSAttr.font =
+[
+ "noJSEvents"
+];
+
+gJSAttr.applet =
+[
+ "noJSEvents"
+];
+
+gJSAttr.isindex =
+[
+ "noJSEvents"
+];
+
+gJSAttr.iframe =
+[
+ "noJSEvents"
+];
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAECSSAttributes.js
@@ -0,0 +1,185 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben "Count XULula" Goodger
+ * Daniel Glazman <glazman@netscape.com>
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// build attribute list in tree form from element attributes
+function BuildCSSAttributeTable()
+{
+ var style = gElement.style;
+ if (style == undefined)
+ {
+ dump("Inline styles undefined\n");
+ return;
+ }
+
+ var declLength = style.length;
+
+ if (declLength == undefined || declLength == 0)
+ {
+ if (declLength == undefined) {
+ dump("Failed to query the number of inline style declarations\n");
+ }
+
+ return;
+ }
+
+ if (declLength > 0)
+ {
+ for (var i = 0; i < declLength; ++i)
+ {
+ var name = style.item(i);
+ var value = style.getPropertyValue(name);
+ AddTreeItem( name, value, "CSSAList", CSSAttrs );
+ }
+ }
+
+ ClearCSSInputWidgets();
+}
+
+function onChangeCSSAttribute()
+{
+ var name = TrimString(gDialog.AddCSSAttributeNameInput.value);
+ if ( !name )
+ return;
+
+ var value = TrimString(gDialog.AddCSSAttributeValueInput.value);
+
+ // First try to update existing attribute
+ // If not found, add new attribute
+ if ( !UpdateExistingAttribute( name, value, "CSSAList" ) && value)
+ AddTreeItem( name, value, "CSSAList", CSSAttrs );
+}
+
+function ClearCSSInputWidgets()
+{
+ gDialog.AddCSSAttributeTree.view.selection.clearSelection();
+ gDialog.AddCSSAttributeNameInput.value ="";
+ gDialog.AddCSSAttributeValueInput.value = "";
+ SetTextboxFocus(gDialog.AddCSSAttributeNameInput);
+}
+
+function onSelectCSSTreeItem()
+{
+ if (!gDoOnSelectTree)
+ return;
+
+ var tree = gDialog.AddCSSAttributeTree;
+ if (tree && tree.view.selection.count)
+ {
+ gDialog.AddCSSAttributeNameInput.value = GetTreeItemAttributeStr(getSelectedItem(tree));
+ gDialog.AddCSSAttributeValueInput.value = GetTreeItemValueStr(getSelectedItem(tree));
+ }
+}
+
+function onInputCSSAttributeName()
+{
+ var attName = TrimString(gDialog.AddCSSAttributeNameInput.value).toLowerCase();
+ var newValue = "";
+
+ var existingValue = GetAndSelectExistingAttributeValue(attName, "CSSAList");
+ if (existingValue)
+ newValue = existingValue;
+
+ gDialog.AddCSSAttributeValueInput.value = newValue;
+}
+
+function editCSSAttributeValue(targetCell)
+{
+ if (IsNotTreeHeader(targetCell))
+ gDialog.AddCSSAttributeValueInput.inputField.select();
+}
+
+function UpdateCSSAttributes()
+{
+ var CSSAList = document.getElementById("CSSAList");
+ var styleString = "";
+ for(var i = 0; i < CSSAList.childNodes.length; i++)
+ {
+ var item = CSSAList.childNodes[i];
+ var name = GetTreeItemAttributeStr(item);
+ var value = GetTreeItemValueStr(item);
+ // this code allows users to be sloppy in typing in values, and enter
+ // things like "foo: " and "bar;". This will trim off everything after the
+ // respective character.
+ if (name.indexOf(":") != -1)
+ name = name.substring(0,name.lastIndexOf(":"));
+ if (value.indexOf(";") != -1)
+ value = value.substring(0,value.lastIndexOf(";"));
+ if (i == (CSSAList.childNodes.length - 1))
+ styleString += name + ": " + value + ";"; // last property
+ else
+ styleString += name + ": " + value + "; ";
+ }
+ if (styleString)
+ {
+ // Use editor transactions if modifying the element directly in the document
+ doRemoveAttribute("style");
+ doSetAttribute("style", styleString); // NOTE BUG 18894!!!
+ }
+ else if (gElement.getAttribute("style"))
+ doRemoveAttribute("style");
+}
+
+function RemoveCSSAttribute()
+{
+ var treechildren = gDialog.AddCSSAttributeTree.lastChild;
+
+ // We only allow 1 selected item
+ if (gDialog.AddCSSAttributeTree.view.selection.count)
+ {
+ var item = getSelectedItem(gDialog.AddCSSAttributeTree);
+
+ // Remove the item from the tree
+ // We always rebuild complete "style" string,
+ // so no list of "removed" items
+ treechildren.removeChild (item);
+
+ ClearCSSInputWidgets();
+ }
+}
+
+function SelectCSSTree( index )
+{
+ gDoOnSelectTree = false;
+ try {
+ gDialog.AddCSSAttributeTree.selectedIndex = index;
+ } catch (e) {}
+ gDoOnSelectTree = true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAEHTMLAttributes.js
@@ -0,0 +1,417 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben "Count XULula" Goodger
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function BuildHTMLAttributeNameList()
+{
+ gDialog.AddHTMLAttributeNameInput.removeAllItems();
+
+ var elementName = gElement.localName.toLowerCase();
+ var attNames = gHTMLAttr[elementName];
+
+ if (attNames && attNames.length)
+ {
+ var menuitem;
+
+ for (var i = 0; i < attNames.length; i++)
+ {
+ var name = attNames[i];
+ var limitFirstChar;
+
+ if (name == "_core")
+ {
+ // Signal to append the common 'core' attributes.
+ for (var j = 0; j < gCoreHTMLAttr.length; j++)
+ {
+ name = gCoreHTMLAttr[j];
+
+ // "limitFirstChar" is the only filtering rule used for core attributes as of 8-20-01
+ // Add more rules if necessary
+ limitFirstChar = name.indexOf("^") >= 0;
+ if (limitFirstChar)
+ {
+ menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name.replace(/\^/g, ""));
+ menuitem.setAttribute("limitFirstChar", "true");
+ }
+ else
+ gDialog.AddHTMLAttributeNameInput.appendItem(name);
+ }
+ }
+ else if (name == "-")
+ {
+ // Signal for separator
+ var popup = gDialog.AddHTMLAttributeNameInput.firstChild;
+ if (popup)
+ {
+ var sep = document.createElementNS(XUL_NS, "menuseparator");
+ if (sep)
+ popup.appendChild(sep);
+ }
+ }
+ else
+ {
+ // Get information about value filtering
+ var forceOneChar = name.indexOf("!") >= 0;
+ var forceInteger = name.indexOf("#") >= 0;
+ var forceSignedInteger = name.indexOf("+") >= 0;
+ var forceIntOrPercent = name.indexOf("%") >= 0;
+ limitFirstChar = name.indexOf("\^") >= 0;
+ //var required = name.indexOf("$") >= 0;
+
+ // Strip flag characters
+ name = name.replace(/[!^#%$+]/g, "");
+
+ menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name);
+ if (menuitem)
+ {
+ // Signify "required" attributes by special style
+ //TODO: Don't do this until next version, when we add
+ // explanatory text and an 'Autofill Required Attributes' button
+ //if (required)
+ // menuitem.setAttribute("class", "menuitem-highlight-1");
+
+ // Set flags to filter value input
+ if (forceOneChar)
+ menuitem.setAttribute("forceOneChar","true");
+ if (limitFirstChar)
+ menuitem.setAttribute("limitFirstChar", "true");
+ if (forceInteger)
+ menuitem.setAttribute("forceInteger", "true");
+ if (forceSignedInteger)
+ menuitem.setAttribute("forceSignedInteger", "true");
+ if (forceIntOrPercent)
+ menuitem.setAttribute("forceIntOrPercent", "true");
+ }
+ }
+ }
+ }
+}
+
+// build attribute list in tree form from element attributes
+function BuildHTMLAttributeTable()
+{
+ var nodeMap = gElement.attributes;
+ var i;
+ if (nodeMap.length > 0)
+ {
+ var added = false;
+ for(i = 0; i < nodeMap.length; i++)
+ {
+ if ( CheckAttributeNameSimilarity( nodeMap[i].nodeName, HTMLAttrs ) ||
+ IsEventHandler( nodeMap[i].nodeName ) ||
+ TrimString( nodeMap[i].nodeName.toLowerCase() ) == "style" ) {
+ continue; // repeated or non-HTML attribute, ignore this one and go to next
+ }
+ var name = nodeMap[i].name.toLowerCase();
+ if ( name.indexOf("_moz") != 0 &&
+ AddTreeItem(name, nodeMap[i].value, "HTMLAList", HTMLAttrs) )
+ {
+ added = true;
+ }
+ }
+
+ if (added)
+ SelectHTMLTree(0);
+ }
+}
+
+// add or select an attribute in the tree widget
+function onChangeHTMLAttribute()
+{
+ var name = TrimString(gDialog.AddHTMLAttributeNameInput.value);
+ if (!name)
+ return;
+
+ var value = TrimString(gDialog.AddHTMLAttributeValueInput.value);
+
+ // First try to update existing attribute
+ // If not found, add new attribute
+ if (!UpdateExistingAttribute( name, value, "HTMLAList" ) && value)
+ AddTreeItem (name, value, "HTMLAList", HTMLAttrs);
+}
+
+function ClearHTMLInputWidgets()
+{
+ gDialog.AddHTMLAttributeTree.view.selection.clearSelection();
+ gDialog.AddHTMLAttributeNameInput.value ="";
+ gDialog.AddHTMLAttributeValueInput.value = "";
+ SetTextboxFocus(gDialog.AddHTMLAttributeNameInput);
+}
+
+function onSelectHTMLTreeItem()
+{
+ if (!gDoOnSelectTree)
+ return;
+
+ var tree = gDialog.AddHTMLAttributeTree;
+ if (tree && tree.view.selection.count)
+ {
+ var inputName = TrimString(gDialog.AddHTMLAttributeNameInput.value).toLowerCase();
+ var selectedItem = getSelectedItem(tree);
+ var selectedName = selectedItem.firstChild.firstChild.getAttribute("label");
+
+ if (inputName == selectedName)
+ {
+ // Already editing selected name - just update the value input
+ gDialog.AddHTMLAttributeValueInput.value = GetTreeItemValueStr(selectedItem);
+ }
+ else
+ {
+ gDialog.AddHTMLAttributeNameInput.value = selectedName;
+
+ // Change value input based on new selected name
+ onInputHTMLAttributeName();
+ }
+ }
+}
+
+function onInputHTMLAttributeName()
+{
+ var attName = TrimString(gDialog.AddHTMLAttributeNameInput.value).toLowerCase();
+
+ // Clear value widget, but prevent triggering update in tree
+ gUpdateTreeValue = false;
+ gDialog.AddHTMLAttributeValueInput.value = "";
+ gUpdateTreeValue = true;
+
+ if (attName)
+ {
+ // Get value list for current attribute name
+ var valueListName;
+
+ // Most elements have the "dir" attribute,
+ // so we have just one array for the allowed values instead
+ // requiring duplicate entries for each element in EdAEAttributes.js
+ if (attName == "dir")
+ valueListName = "all_dir";
+ else
+ valueListName = gElement.localName.toLowerCase() + "_" + attName;
+
+ // Strip off leading "_" we sometimes use (when element name is reserved word)
+ if (valueListName[0] == "_")
+ valueListName = valueListName.slice(1);
+
+ var newValue = "";
+ var listLen = 0;
+
+ // Index to which widget we were using to edit the value
+ var deckIndex = gDialog.AddHTMLAttributeValueDeck.getAttribute("selectedIndex");
+
+ if (valueListName in gHTMLAttr)
+ {
+ var valueList = gHTMLAttr[valueListName];
+
+ listLen = valueList.length;
+ if (listLen > 0)
+ newValue = valueList[0];
+
+ // Note: For case where "value list" is actually just
+ // one (default) item, don't use menulist for that
+ if (listLen > 1)
+ {
+ gDialog.AddHTMLAttributeValueMenulist.removeAllItems();
+
+ if (deckIndex != "1")
+ {
+ // Switch to using editable menulist
+ gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueMenulist;
+ gDialog.AddHTMLAttributeValueDeck.setAttribute("selectedIndex", "1");
+ }
+ // Rebuild the list
+ for (var i = 0; i < listLen; i++)
+ {
+ if (valueList[i] == "-")
+ {
+ // Signal for separator
+ var popup = gDialog.AddHTMLAttributeValueInput.firstChild;
+ if (popup)
+ {
+ var sep = document.createElementNS(XUL_NS, "menuseparator");
+ if (sep)
+ popup.appendChild(sep);
+ }
+ } else {
+ gDialog.AddHTMLAttributeValueMenulist.appendItem(valueList[i]);
+ }
+ }
+ }
+ }
+
+ if (listLen <= 1 && deckIndex != "0")
+ {
+ // No list: Use textbox for input instead
+ gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueTextbox;
+ gDialog.AddHTMLAttributeValueDeck.setAttribute("selectedIndex", "0");
+ }
+
+ // If attribute already exists in tree, use associated value,
+ // else use default found above
+ var existingValue = GetAndSelectExistingAttributeValue(attName, "HTMLAList");
+ if (existingValue)
+ newValue = existingValue;
+
+ gDialog.AddHTMLAttributeValueInput.value = newValue;
+ }
+}
+
+function onInputHTMLAttributeValue()
+{
+ if (!gUpdateTreeValue)
+ return;
+
+ var name = TrimString(gDialog.AddHTMLAttributeNameInput.value);
+ if (!name)
+ return;
+
+ // Trim spaces only from left since we must allow spaces within the string
+ // (we always reset the input field's value below)
+ var value = TrimStringLeft(gDialog.AddHTMLAttributeValueInput.value);
+ if (value)
+ {
+ // Do value filtering based on type of attribute
+ // (Do not use "forceInteger()" to avoid multiple
+ // resetting of input's value and flickering)
+ var selectedItem = gDialog.AddHTMLAttributeNameInput.selectedItem;
+
+ if (selectedItem)
+ {
+ if ( selectedItem.getAttribute("forceOneChar") == "true" &&
+ value.length > 1 )
+ value = value.slice(0, 1);
+
+ if ( selectedItem.getAttribute("forceIntOrPercent") == "true" )
+ {
+ // Allow integer with optional "%" as last character
+ var percent = TrimStringRight(value).slice(-1);
+ value = value.replace(/\D+/g,"");
+ if (percent == "%")
+ value += percent;
+ }
+ else if ( selectedItem.getAttribute("forceInteger") == "true" )
+ {
+ value = value.replace(/\D+/g,"");
+ }
+ else if ( selectedItem.getAttribute("forceSignedInteger") == "true" )
+ {
+ // Allow integer with optional "+" or "-" as first character
+ var sign = value[0];
+ value = value.replace(/\D+/g,"");
+ if (sign == "+" || sign == "-")
+ value = sign + value;
+ }
+
+ // Special case attributes
+ if (selectedItem.getAttribute("limitFirstChar") == "true")
+ {
+ // Limit first character to letter, and all others to
+ // letters, numbers, and a few others
+ value = value.replace(/^[^a-zA-Z\u0080-\uFFFF]/, "").replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g,'');
+ }
+
+ // Update once only if it changed
+ if (value != gDialog.AddHTMLAttributeValueInput.value)
+ gDialog.AddHTMLAttributeValueInput.value = value;
+ }
+ }
+
+ // Update value in the tree list
+ // If not found, add new attribute
+ if ( !UpdateExistingAttribute(name, value, "HTMLAList" ) && value)
+ AddTreeItem(name, value, "HTMLAList", HTMLAttrs);
+}
+
+function editHTMLAttributeValue(targetCell)
+{
+ if (IsNotTreeHeader(targetCell))
+ gDialog.AddHTMLAttributeValueInput.inputField.select();
+}
+
+
+// update the object with added and removed attributes
+function UpdateHTMLAttributes()
+{
+ var HTMLAList = document.getElementById("HTMLAList");
+ var i;
+
+ // remove removed attributes
+ for (i = 0; i < HTMLRAttrs.length; i++)
+ {
+ var name = HTMLRAttrs[i];
+
+ if (gElement.hasAttribute(name))
+ doRemoveAttribute(name);
+ }
+
+ // Set added or changed attributes
+ for( i = 0; i < HTMLAList.childNodes.length; i++)
+ {
+ var item = HTMLAList.childNodes[i];
+ doSetAttribute( GetTreeItemAttributeStr(item), GetTreeItemValueStr(item));
+ }
+}
+
+function RemoveHTMLAttribute()
+{
+ var treechildren = gDialog.AddHTMLAttributeTree.lastChild;
+
+ // We only allow 1 selected item
+ if (gDialog.AddHTMLAttributeTree.view.selection.count)
+ {
+ var item = getSelectedItem(gDialog.AddHTMLAttributeTree);
+ var attr = GetTreeItemAttributeStr(item);
+
+ // remove the item from the attribute array
+ HTMLRAttrs[HTMLRAttrs.length] = attr;
+ RemoveNameFromAttArray(attr, HTMLAttrs);
+
+ // Remove the item from the tree
+ treechildren.removeChild(item);
+
+ // Clear inputs and selected item in tree
+ ClearHTMLInputWidgets();
+ }
+}
+
+function SelectHTMLTree( index )
+{
+
+ gDoOnSelectTree = false;
+ try {
+ gDialog.AddHTMLAttributeTree.selectedIndex = index;
+ } catch (e) {}
+ gDoOnSelectTree = true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAEJSEAttributes.js
@@ -0,0 +1,239 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben "Count XULula" Goodger
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function BuildJSEAttributeNameList()
+{
+ gDialog.AddJSEAttributeNameList.removeAllItems();
+
+ // Get events specific to current element
+ var elementName = gElement.localName.toLowerCase();
+ if (elementName in gJSAttr)
+ {
+ var attNames = gJSAttr[elementName];
+ var i;
+ var popup;
+ var sep;
+
+ if (attNames && attNames.length)
+ {
+ // Since we don't allow user-editable JS events yet (but we will soon)
+ // simply remove the JS tab to not allow adding JS events
+ if (attNames[0] == "noJSEvents")
+ {
+ var tab = document.getElementById("tabJSE");
+ if (tab)
+ tab.parentNode.removeChild(tab);
+
+ return;
+ }
+
+ for (i = 0; i < attNames.length; i++)
+ gDialog.AddJSEAttributeNameList.appendItem(attNames[i], attNames[i]);
+
+ popup = gDialog.AddJSEAttributeNameList.firstChild;
+ if (popup)
+ {
+ sep = document.createElementNS(XUL_NS, "menuseparator");
+ if (sep)
+ popup.appendChild(sep);
+ }
+ }
+ }
+
+ // Always add core JS events unless we aborted above
+ for (i = 0; i < gCoreJSEvents.length; i++)
+ {
+ if (gCoreJSEvents[i] == "-")
+ {
+ if (!popup)
+ popup = gDialog.AddJSEAttributeNameList.firstChild;
+
+ sep = document.createElementNS(XUL_NS, "menuseparator");
+
+ if (popup && sep)
+ popup.appendChild(sep);
+ }
+ else
+ gDialog.AddJSEAttributeNameList.appendItem(gCoreJSEvents[i], gCoreJSEvents[i]);
+ }
+
+ gDialog.AddJSEAttributeNameList.selectedIndex = 0;
+
+ // Use current name and value of first tree item if it exists
+ onSelectJSETreeItem();
+}
+
+// build attribute list in tree form from element attributes
+function BuildJSEAttributeTable()
+{
+ var nodeMap = gElement.attributes;
+ if (nodeMap.length > 0)
+ {
+ var added = false;
+ for (var i = 0; i < nodeMap.length; i++)
+ {
+ if( CheckAttributeNameSimilarity( nodeMap[i].nodeName, JSEAttrs ) )
+ continue; // repeated or non-JS handler, ignore this one and go to next
+ if( !IsEventHandler( nodeMap[i].nodeName ) )
+ continue; // attribute isn't an event handler.
+ var name = nodeMap[i].nodeName.toLowerCase();
+ var value = gElement.getAttribute(nodeMap[i].nodeName);
+ if (AddTreeItem( name, value, "JSEAList", JSEAttrs )) // add item to tree
+ added = true;
+ }
+
+ // Select first item
+ if (added)
+ gDialog.AddJSEAttributeTree.selectedIndex = 0;
+ }
+}
+
+// check to see if given string is an event handler.
+function IsEventHandler( which )
+{
+ var handlerName = which.toLowerCase();
+ var firstTwo = handlerName.substring(0,2);
+ if (firstTwo == "on")
+ return true;
+ else
+ return false;
+}
+
+function onSelectJSEAttribute()
+{
+ if(!gDoOnSelectTree)
+ return;
+
+ gDialog.AddJSEAttributeValueInput.value =
+ GetAndSelectExistingAttributeValue(gDialog.AddJSEAttributeNameList.label, "JSEAList");
+}
+
+function onSelectJSETreeItem()
+{
+ var tree = gDialog.AddJSEAttributeTree;
+ if (tree && tree.view.selection.count)
+ {
+ // Select attribute name in list
+ gDialog.AddJSEAttributeNameList.value = GetTreeItemAttributeStr(getSelectedItem(tree));
+
+ // Set value input to that in tree (no need to update this in the tree)
+ gUpdateTreeValue = false;
+ gDialog.AddJSEAttributeValueInput.value = GetTreeItemValueStr(getSelectedItem(tree));
+ gUpdateTreeValue = true;
+ }
+}
+
+function onInputJSEAttributeValue()
+{
+ if (gUpdateTreeValue)
+ {
+
+ var name = TrimString(gDialog.AddJSEAttributeNameList.label);
+ var value = TrimString(gDialog.AddJSEAttributeValueInput.value);
+
+ // Update value in the tree list
+ // Since we have a non-editable menulist,
+ // we MUST automatically add the event attribute if it doesn't exist
+ if (!UpdateExistingAttribute( name, value, "JSEAList" ) && value)
+ AddTreeItem( name, value, "JSEAList", JSEAttrs );
+ }
+}
+
+function editJSEAttributeValue(targetCell)
+{
+ if (IsNotTreeHeader(targetCell))
+ gDialog.AddJSEAttributeValueInput.inputField.select();
+}
+
+function UpdateJSEAttributes()
+{
+ var JSEAList = document.getElementById("JSEAList");
+ var i;
+
+ // remove removed attributes
+ for (i = 0; i < JSERAttrs.length; i++)
+ {
+ var name = JSERAttrs[i];
+
+ if (gElement.hasAttribute(name))
+ doRemoveAttribute(name);
+ }
+
+ // Add events
+ for (i = 0; i < JSEAList.childNodes.length; i++)
+ {
+ var item = JSEAList.childNodes[i];
+
+ // set the event handler
+ doSetAttribute( GetTreeItemAttributeStr(item), GetTreeItemValueStr(item) );
+ }
+}
+
+function RemoveJSEAttribute()
+{
+ var treechildren = gDialog.AddJSEAttributeTree.lastChild;
+
+ // This differs from HTML and CSS panels:
+ // We reselect after removing, because there is not
+ // editable attribute name input, so we can't clear that
+ // like we do in other panels
+ var newIndex = gDialog.AddJSEAttributeTree.selectedIndex;
+
+ // We only allow 1 selected item
+ if (gDialog.AddJSEAttributeTree.view.selection.count)
+ {
+ var item = getSelectedItem(gDialog.AddJSEAttributeTree);
+
+ // Name is the text of the treecell
+ var attr = GetTreeItemAttributeStr(item);
+
+ // remove the item from the attribute array
+ if (newIndex >= (JSEAttrs.length-1))
+ newIndex--;
+
+ // remove the item from the attribute array
+ JSERAttrs[JSERAttrs.length] = attr;
+ RemoveNameFromAttArray(attr, JSEAttrs);
+
+ // Remove the item from the tree
+ treechildren.removeChild (item);
+
+ // Reselect an item
+ gDialog.AddJSEAttributeTree.selectedIndex = newIndex;
+ }
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAdvancedEdit.js
@@ -0,0 +1,369 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben "Count XULula" Goodger
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/************** GLOBALS **************/
+var gElement = null; // handle to actual element edited
+
+var HTMLAttrs = []; // html attributes
+var CSSAttrs = []; // css attributes
+var JSEAttrs = []; // js events
+
+var HTMLRAttrs = []; // removed html attributes
+var JSERAttrs = []; // removed js events
+
+/* Set false to allow changing selection in tree
+ without doing "onselect" handler actions
+*/
+var gDoOnSelectTree = true;
+var gUpdateTreeValue = true;
+
+/************** INITIALISATION && SETUP **************/
+
+/**
+ * function : void Startup();
+ * parameters : none
+ * returns : none
+ * desc. : startup and initialisation, prepares dialog.
+ **/
+function Startup()
+{
+ var editor = GetCurrentEditor();
+
+ // Element to edit is passed in
+ if (!editor || !window.arguments[1])
+ {
+ dump("Advanced Edit: No editor or element to edit not supplied\n");
+ window.close();
+ return;
+ }
+ // This is the return value for the parent,
+ // who only needs to know if OK was clicked
+ window.opener.AdvancedEditOK = false;
+
+ // The actual element edited (not a copy!)
+ gElement = window.arguments[1];
+
+ // place the tag name in the header
+ var tagLabel = document.getElementById("tagLabel");
+ tagLabel.setAttribute("value", ("<" + gElement.localName + ">"));
+
+ // Create dialog object to store controls for easy access
+ gDialog.AddHTMLAttributeNameInput = document.getElementById("AddHTMLAttributeNameInput");
+
+ // We use a <deck> to switch between editable menulist and textbox
+ gDialog.AddHTMLAttributeValueDeck = document.getElementById("AddHTMLAttributeValueDeck");
+ gDialog.AddHTMLAttributeValueMenulist = document.getElementById("AddHTMLAttributeValueMenulist");
+ gDialog.AddHTMLAttributeValueTextbox = document.getElementById("AddHTMLAttributeValueTextbox");
+ gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueTextbox;
+
+ gDialog.AddHTMLAttributeTree = document.getElementById("HTMLATree");
+ gDialog.AddCSSAttributeNameInput = document.getElementById("AddCSSAttributeNameInput");
+ gDialog.AddCSSAttributeValueInput = document.getElementById("AddCSSAttributeValueInput");
+ gDialog.AddCSSAttributeTree = document.getElementById("CSSATree");
+ gDialog.AddJSEAttributeNameList = document.getElementById("AddJSEAttributeNameList");
+ gDialog.AddJSEAttributeValueInput = document.getElementById("AddJSEAttributeValueInput");
+ gDialog.AddJSEAttributeTree = document.getElementById("JSEATree");
+ gDialog.okButton = document.documentElement.getButton("accept");
+
+ // build the attribute trees
+ BuildHTMLAttributeTable();
+ BuildCSSAttributeTable();
+ BuildJSEAttributeTable();
+
+ // Build attribute name arrays for menulists
+ BuildJSEAttributeNameList();
+ BuildHTMLAttributeNameList();
+ // No menulists for CSS panel (yet)
+
+ // Set focus to Name editable menulist in HTML panel
+ SetTextboxFocus(gDialog.AddHTMLAttributeNameInput);
+
+ // size the dialog properly
+ window.sizeToContent();
+
+ SetWindowLocation();
+}
+
+/**
+ * function : bool onAccept ( void );
+ * parameters : none
+ * returns : boolean true to close the window
+ * desc. : event handler for ok button
+ **/
+function onAccept()
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+ try {
+ // Update our gElement attributes
+ UpdateHTMLAttributes();
+ UpdateCSSAttributes();
+ UpdateJSEAttributes();
+ } catch(ex) {
+ dump(ex);
+ }
+ editor.endTransaction();
+
+ window.opener.AdvancedEditOK = true;
+ SaveWindowLocation();
+
+ return true; // do close the window
+}
+
+// Helpers for removing and setting attributes
+// Use editor transactions if modifying the element already in the document
+// (Temporary element from a property dialog won't have a parent node)
+function doRemoveAttribute(attrib)
+{
+ try {
+ var editor = GetCurrentEditor();
+ if (gElement.parentNode)
+ editor.removeAttribute(gElement, attrib);
+ else
+ gElement.removeAttribute(attrib);
+ } catch(ex) {}
+}
+
+function doSetAttribute(attrib, value)
+{
+ try {
+ var editor = GetCurrentEditor();
+ if (gElement.parentNode)
+ editor.setAttribute(gElement, attrib, value);
+ else
+ gElement.setAttribute(attrib, value);
+ } catch(ex) {}
+}
+
+/**
+ * function : bool CheckAttributeNameSimilarity ( string attName, array attArray );
+ * parameters : attribute to look for, array of current attributes
+ * returns : true if attribute already exists, false if it does not
+ * desc. : checks to see if any other attributes by the same name as the arg supplied
+ * already exist.
+ **/
+function CheckAttributeNameSimilarity(attName, attArray)
+{
+ for (var i = 0; i < attArray.length; i++)
+ {
+ if (attName.toLowerCase() == attArray[i].toLowerCase())
+ return true;
+ }
+ return false;
+}
+
+/**
+ * function : bool UpdateExistingAttribute ( string attName, string attValue, string treeChildrenId );
+ * parameters : attribute to look for, new value, ID of <treeChildren> node in XUL tree
+ * returns : true if attribute already exists in tree, false if it does not
+ * desc. : checks to see if any other attributes by the same name as the arg supplied
+ * already exist while setting the associated value if different from current value
+ **/
+function UpdateExistingAttribute( attName, attValue, treeChildrenId )
+{
+ var treeChildren = document.getElementById(treeChildrenId);
+ if (!treeChildren)
+ return false;
+
+ var name;
+ var i;
+ attName = TrimString(attName).toLowerCase();
+ attValue = TrimString(attValue);
+
+ for (i = 0; i < treeChildren.childNodes.length; i++)
+ {
+ var item = treeChildren.childNodes[i];
+ name = GetTreeItemAttributeStr(item);
+ if (name.toLowerCase() == attName)
+ {
+ // Set the text in the "value' column treecell
+ SetTreeItemValueStr(item, attValue);
+
+ // Select item just changed,
+ // but don't trigger the tree's onSelect handler
+ gDoOnSelectTree = false;
+ try {
+ selectTreeItem(treeChildren, item);
+ } catch (e) {}
+ gDoOnSelectTree = true;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * function : string GetAndSelectExistingAttributeValue ( string attName, string treeChildrenId );
+ * parameters : attribute to look for, ID of <treeChildren> node in XUL tree
+ * returns : value in from the tree or empty string if name not found
+ **/
+function GetAndSelectExistingAttributeValue( attName, treeChildrenId )
+{
+ if (!attName)
+ return "";
+
+ var treeChildren = document.getElementById(treeChildrenId);
+ var name;
+ var i;
+
+ for (i = 0; i < treeChildren.childNodes.length; i++)
+ {
+ var item = treeChildren.childNodes[i];
+ name = GetTreeItemAttributeStr(item);
+ if (name.toLowerCase() == attName.toLowerCase())
+ {
+ // Select item in the tree
+ // but don't trigger the tree's onSelect handler
+ gDoOnSelectTree = false;
+ try {
+ selectTreeItem(treeChildren, item);
+ } catch (e) {}
+ gDoOnSelectTree = true;
+
+ // Get the text in the "value' column treecell
+ return GetTreeItemValueStr(item);
+ }
+ }
+
+ // Attribute doesn't exist in tree, so remove selection
+ gDoOnSelectTree = false;
+ try {
+ treeChildren.parentNode.view.selection.clearSelection();
+ } catch (e) {}
+ gDoOnSelectTree = true;
+
+ return "";
+}
+
+/* Tree structure:
+ <treeItem>
+ <treeRow>
+ <treeCell> // Name Cell
+ <treeCell // Value Cell
+*/
+function GetTreeItemAttributeStr(treeItem)
+{
+ if (treeItem)
+ return TrimString(treeItem.firstChild.firstChild.getAttribute("label"));
+
+ return "";
+}
+
+function GetTreeItemValueStr(treeItem)
+{
+ if (treeItem)
+ return TrimString(treeItem.firstChild.lastChild.getAttribute("label"));
+
+ return "";
+}
+
+function SetTreeItemValueStr(treeItem, value)
+{
+ if (treeItem && GetTreeItemValueStr(treeItem) != value)
+ treeItem.firstChild.lastChild.setAttribute("label", value);
+}
+
+function IsNotTreeHeader(treeCell)
+{
+ if (treeCell)
+ return (treeCell.parentNode.parentNode.nodeName != "treehead");
+
+ return false;
+}
+
+function RemoveNameFromAttArray(attName, attArray)
+{
+ for (var i=0; i < attArray.length; i++)
+ {
+ if (attName.toLowerCase() == attArray[i].toLowerCase())
+ {
+ // Remove 1 array item
+ attArray.splice(i,1);
+ break;
+ }
+ }
+}
+
+// adds a generalised treeitem.
+function AddTreeItem ( name, value, treeChildrenId, attArray )
+{
+ attArray[attArray.length] = name;
+ var treeChildren = document.getElementById ( treeChildrenId );
+ var treeitem = document.createElementNS ( XUL_NS, "treeitem" );
+ var treerow = document.createElementNS ( XUL_NS, "treerow" );
+
+ var attrCell = document.createElementNS ( XUL_NS, "treecell" );
+ attrCell.setAttribute( "class", "propertylist" );
+ attrCell.setAttribute( "label", name );
+
+ var valueCell = document.createElementNS ( XUL_NS, "treecell" );
+ valueCell.setAttribute( "class", "propertylist" );
+ valueCell.setAttribute( "label", value );
+
+ treerow.appendChild ( attrCell );
+ treerow.appendChild ( valueCell );
+ treeitem.appendChild ( treerow );
+ treeChildren.appendChild ( treeitem );
+
+ // Select item just added,
+ // but suppress calling the onSelect handler
+ gDoOnSelectTree = false;
+ try {
+ selectTreeItem(treeChildren, treeitem);
+ } catch (e) {}
+ gDoOnSelectTree = true;
+
+ return treeitem;
+}
+
+function selectTreeItem(treeChildren, item)
+{
+ var index = treeChildren.parentNode.contentView.getIndexOfItem(item);
+ treeChildren.parentNode.view.selection.select(index);
+}
+
+function getSelectedItem(tree)
+{
+ if (tree.view.selection.count == 1)
+ return tree.contentView.getItemAtIndex(tree.currentIndex);
+ else
+ return null;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdAdvancedEdit.xul
@@ -0,0 +1,220 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Ben "Count XULula" Goodger
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- first checkin of the year 2000! -->
+<!-- Ben Goodger, 12:50AM, 01/00/00 NZST -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<!-- May not need this here -->
+<!-- <?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?> -->
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdAdvancedEdit.dtd">
+<dialog title="&WindowTitle.label;"
+ id="advancedEditDlg"
+ style="width: 40em;"
+ xmlns ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <!-- element page functions -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdAEHTMLAttributes.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdAECSSAttributes.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdAEJSEAttributes.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdAEAttributes.js"/>
+
+ <!-- global dialog functions -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdAdvancedEdit.js"/>
+
+ <broadcaster id="args" value=""/>
+
+ <hbox>
+ <label value="¤tattributesfor.label;"/>
+ <label class="header" id="tagLabel"/>
+ </hbox>
+
+ <separator class="thin"/>
+
+ <tabbox flex="1">
+ <tabs>
+ <tab label="&tabHTML.label;"/>
+ <tab label="&tabCSS.label;"/>
+ <tab label="&tabJSE.label;" id="tabJSE"/>
+ </tabs>
+ <tabpanels flex="1">
+ <!-- ============================================================== -->
+ <!-- HTML Attributes -->
+ <!-- ============================================================== -->
+ <vbox>
+ <tree id="HTMLATree" class="AttributesTree" flex="1"
+ hidecolumnpicker="true" seltype="single"
+ onselect="onSelectHTMLTreeItem();"
+ onclick="onSelectHTMLTreeItem();"
+ ondblclick="editHTMLAttributeValue(event.target);">
+ <treecols>
+ <treecol id="HTMLAttrCol" flex="35" label="&tree.attributeHeader.label;"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="HTMLValCol" flex="65" label="&tree.valueHeader.label;"/>
+ </treecols>
+ <treechildren id="HTMLAList" class="gridlines" flex="1"/>
+ </tree>
+ <hbox align="center">
+ <label value="&editAttribute.label;"/>
+ <spacer flex="1"/>
+ <button label="&removeAttribute.label;" oncommand="RemoveHTMLAttribute();"/>
+ </hbox>
+ <grid>
+ <columns>
+ <column flex="1"/><column flex="1"/>
+ </columns>
+ <rows>
+ <row equalsize="always">
+ <label control="AddHTMLAttributeNameInput" value="&AttName.label;"/>
+ <label control="AddHTMLAttributeValueInput" value="&AttValue.label;"/>
+ </row>
+ <row align="top" equalsize="always">
+ <!-- Lists are built at runtime -->
+ <menulist id="AddHTMLAttributeNameInput" editable="true" flex="1"
+ oninput="onInputHTMLAttributeName();"
+ onchange="onChangeHTMLAttribute();"/>
+ <deck id="AddHTMLAttributeValueDeck" selectedIndex="0">
+ <hbox align="top">
+ <textbox id="AddHTMLAttributeValueTextbox" flex="1"
+ oninput="onInputHTMLAttributeValue();"/>
+ </hbox>
+ <hbox align="top">
+ <menulist id="AddHTMLAttributeValueMenulist" editable="true" flex="1"
+ oninput="onInputHTMLAttributeValue();"/>
+ </hbox>
+ </deck>
+ </row>
+ </rows>
+ </grid>
+ </vbox>
+ <!-- ============================================================== -->
+ <!-- CSS Attributes -->
+ <!-- ============================================================== -->
+ <vbox>
+ <tree id="CSSATree" class="AttributesTree" flex="1"
+ hidecolumnpicker="true" seltype="single"
+ onselect="onSelectCSSTreeItem();"
+ onclick="onSelectCSSTreeItem();"
+ ondblclick="editCSSAttributeValue(event.target);">
+ <treecols>
+ <treecol id="CSSPropCol" flex="35" label="&tree.propertyHeader.label;"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="CSSValCol" flex="65" label="&tree.valueHeader.label;"/>
+ </treecols>
+ <treechildren id="CSSAList" class="gridlines" flex="1"/>
+ </tree>
+ <hbox align="center">
+ <label value="&editAttribute.label;"/>
+ <spacer flex="1"/>
+ <button label="&removeAttribute.label;" oncommand="RemoveCSSAttribute();"/>
+ </hbox>
+ <grid>
+ <columns>
+ <column flex="1"/><column flex="1"/>
+ </columns>
+ <rows>
+ <row equalsize="always">
+ <label value="&PropertyName.label;"/>
+ <label value="&AttValue.label;"/>
+ </row>
+ <row align="top" equalsize="always">
+ <textbox id="AddCSSAttributeNameInput" flex="1"
+ oninput="onInputCSSAttributeName();"
+ onchange="onChangeCSSAttribute();"/>
+ <textbox id="AddCSSAttributeValueInput" flex="1"
+ oninput="onChangeCSSAttribute();"/>
+ </row>
+ </rows>
+ </grid>
+ </vbox>
+ <!-- ============================================================== -->
+ <!-- JavaScript Event Handlers -->
+ <!-- ============================================================== -->
+ <vbox>
+ <tree id="JSEATree" class="AttributesTree" flex="1"
+ hidecolumnpicker="true" seltype="single"
+ onselect="onSelectJSETreeItem();"
+ onclick="onSelectJSETreeItem();"
+ ondblclick="editJSEAttributeValue(event.target);">
+ <treecols>
+ <treecol id="AttrCol" flex="35" label="&tree.attributeHeader.label;"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="HeaderCol" flex="65" label="&tree.valueHeader.label;"/>
+ </treecols>
+ <treechildren id="JSEAList" class="gridlines" flex="1"/>
+ </tree>
+ <hbox align="center">
+ <label value="&editAttribute.label;"/>
+ <spacer flex="1"/>
+ <button label="&removeAttribute.label;" oncommand="RemoveJSEAttribute()"/>
+ </hbox>
+ <grid>
+ <columns>
+ <column flex="1"/><column flex="1"/>
+ </columns>
+ <rows>
+ <row equalsize="always">
+ <label value="&AttName.label;"/>
+ <label value="&AttValue.label;"/>
+ </row>
+ <row align="top" equalsize="always">
+ <!-- List is built at runtime -->
+ <menulist id="AddJSEAttributeNameList" flex="1"
+ oncommand="onSelectJSEAttribute();">
+ <menupopup/>
+ </menulist>
+ <textbox id="AddJSEAttributeValueInput" flex="1"
+ oninput="onInputJSEAttributeValue();"/>
+ </row>
+ </rows>
+ </grid>
+ </vbox>
+ </tabpanels>
+ </tabbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdButtonProps.js
@@ -0,0 +1,178 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Button Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var insertNew;
+var buttonElement;
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ gDialog = {
+ buttonType: document.getElementById("ButtonType"),
+ buttonName: document.getElementById("ButtonName"),
+ buttonValue: document.getElementById("ButtonValue"),
+ buttonDisabled: document.getElementById("ButtonDisabled"),
+ buttonTabIndex: document.getElementById("ButtonTabIndex"),
+ buttonAccessKey: document.getElementById("ButtonAccessKey"),
+ MoreSection: document.getElementById("MoreSection"),
+ MoreFewerButton: document.getElementById("MoreFewerButton"),
+ RemoveButton: document.getElementById("RemoveButton")
+ };
+
+ // Get a single selected button element
+ const kTagName = "button";
+ try {
+ buttonElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
+
+ if (buttonElement)
+ // We found an element and don't need to insert one
+ insertNew = false;
+ else
+ {
+ insertNew = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ buttonElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
+
+ if (!buttonElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ // Hide button removing existing button
+ gDialog.RemoveButton.hidden = true;
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = buttonElement.cloneNode(false);
+
+ InitDialog();
+
+ InitMoreFewer();
+
+ gDialog.buttonType.focus();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ var type = globalElement.getAttribute("type");
+ var index = 0;
+ switch (type)
+ {
+ case "button":
+ index = 2;
+ break;
+ case "reset":
+ index = 1;
+ break;
+ }
+ gDialog.buttonType.selectedIndex = index;
+ gDialog.buttonName.value = globalElement.getAttribute("name");
+ gDialog.buttonValue.value = globalElement.getAttribute("value");
+ gDialog.buttonDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
+ gDialog.buttonTabIndex.value = globalElement.getAttribute("tabindex");
+ gDialog.buttonAccessKey.value = globalElement.getAttribute("accesskey");
+}
+
+function RemoveButton()
+{
+ RemoveContainer(buttonElement);
+ SaveWindowLocation();
+ window.close();
+}
+
+function ValidateData()
+{
+ var attributes = {
+ type: ["", "reset", "button"][gDialog.buttonType.selectedIndex],
+ name: gDialog.buttonName.value,
+ value: gDialog.buttonValue.value,
+ tabindex: gDialog.buttonTabIndex.value,
+ accesskey: gDialog.buttonAccessKey.value
+ };
+ for (var a in attributes)
+ {
+ if (attributes[a])
+ globalElement.setAttribute(a, attributes[a]);
+ else
+ globalElement.removeAttribute(a);
+ }
+ if (gDialog.buttonDisabled.checked)
+ globalElement.setAttribute("disabled", "");
+ else
+ globalElement.removeAttribute("disabled");
+ return true;
+}
+
+function onAccept()
+{
+ // All values are valid - copy to actual element in doc or
+ // element created to insert
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ editor.cloneAttributes(buttonElement, globalElement);
+
+ if (insertNew)
+ {
+ if (!InsertElementAroundSelection(buttonElement))
+ {
+ buttonElement.innerHTML = editor.outputToString("text/html", kOutputSelectionOnly);
+ editor.insertElementAtSelection(buttonElement, true);
+ }
+ }
+
+ SaveWindowLocation();
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdButtonProps.xul
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Button Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorButtonProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdButtonProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&Settings.label;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="ButtonType" value="&ButtonType.label;" accesskey="&ButtonType.accesskey;"/>
+ <menulist id="ButtonType">
+ <menupopup>
+ <menuitem label="&submit.value;"/>
+ <menuitem label="&reset.value;"/>
+ <menuitem label="&button.value;"/>
+ </menupopup>
+ </menulist>
+ </row>
+ <row align="center">
+ <label control="ButtonName" value="&ButtonName.label;" accesskey="&ButtonName.accesskey;"/>
+ <textbox id="ButtonName"/>
+ </row>
+ <row align="center">
+ <label control="ButtonValue" value="&ButtonValue.label;" accesskey="&ButtonValue.accesskey;"/>
+ <textbox id="ButtonValue"/>
+ </row>
+ </rows>
+ </grid>
+ <hbox>
+ <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
+ </hbox>
+ <grid id="MoreSection"><columns><column/><column/></columns>
+ <rows>
+ <row>
+ <spacer/>
+ <checkbox id="ButtonDisabled" label="&ButtonDisabled.label;" accesskey="&ButtonDisabled.accesskey;"/>
+ </row>
+ <row align="center">
+ <label control="ButtonTabIndex" value="&tabIndex.label;" accesskey="&tabIndex.accesskey;"/>
+ <hbox>
+ <textbox id="ButtonTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="ButtonAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
+ <hbox>
+ <textbox id="ButtonAccessKey" class="narrow"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <hbox flex="1" style="margin-top: 0.2em">
+ <button id="RemoveButton" label="&RemoveButton.label;" accesskey="&RemoveButton.accesskey;" oncommand="RemoveButton();"/>
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdColorPicker.js
@@ -0,0 +1,341 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Daniel Glazman (glazman@netscape.com)
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+//Cancel() is in EdDialogCommon.js
+var insertNew = true;
+var tagname = "TAG NAME"
+var gColor = "";
+var LastPickedColor = "";
+var ColorType = "Text";
+var TextType = false;
+var HighlightType = false;
+var TableOrCell = false;
+var LastPickedIsDefault = true;
+var NoDefault = false;
+var gColorObj;
+
+// dialog initialization code
+function Startup()
+{
+ if (!window.arguments[1])
+ {
+ dump("EdColorPicker: Missing color object param\n");
+ return;
+ }
+
+ // window.arguments[1] is object to get initial values and return color data
+ gColorObj = window.arguments[1];
+ gColorObj.Cancel = false;
+
+ gDialog.ColorPicker = document.getElementById("ColorPicker");
+ gDialog.ColorInput = document.getElementById("ColorInput");
+ gDialog.LastPickedButton = document.getElementById("LastPickedButton");
+ gDialog.LastPickedColor = document.getElementById("LastPickedColor");
+ gDialog.CellOrTableGroup = document.getElementById("CellOrTableGroup");
+ gDialog.TableRadio = document.getElementById("TableRadio");
+ gDialog.CellRadio = document.getElementById("CellRadio");
+ gDialog.ColorSwatch = document.getElementById("ColorPickerSwatch");
+ gDialog.Ok = document.documentElement.getButton("accept");
+
+ // The type of color we are setting:
+ // text: Text, Link, ActiveLink, VisitedLink,
+ // or background: Page, Table, or Cell
+ if (gColorObj.Type)
+ {
+ ColorType = gColorObj.Type;
+ // Get string for dialog title from passed-in type
+ // (note constraint on editor.properties string name)
+ var prefs = GetPrefs();
+ var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
+
+ if (GetCurrentEditor())
+ {
+ if (ColorType == "Page" && IsCSSPrefChecked && IsHTMLEditor())
+ document.title = GetString("BlockColor");
+ else
+ document.title = GetString(ColorType + "Color");
+ }
+ }
+
+ gDialog.ColorInput.value = "";
+ var tmpColor;
+ var haveTableRadio = false;
+
+ switch (ColorType)
+ {
+ case "Page":
+ tmpColor = gColorObj.PageColor;
+ if (tmpColor && tmpColor.toLowerCase() != "window")
+ gColor = tmpColor;
+ break;
+ case "Table":
+ if (gColorObj.TableColor)
+ gColor = gColorObj.TableColor;
+ break;
+ case "Cell":
+ if (gColorObj.CellColor)
+ gColor = gColorObj.CellColor;
+ break;
+ case "TableOrCell":
+ TableOrCell = true;
+ document.getElementById("TableOrCellGroup").collapsed = false;
+ haveTableRadio = true;
+ if (gColorObj.SelectedType == "Cell")
+ {
+ gColor = gColorObj.CellColor;
+ gDialog.CellOrTableGroup.selectedItem = gDialog.CellRadio;
+ gDialog.CellRadio.focus();
+ }
+ else
+ {
+ gColor = gColorObj.TableColor;
+ gDialog.CellOrTableGroup.selectedItem = gDialog.TableRadio;
+ gDialog.TableRadio.focus();
+ }
+ break;
+ case "Highlight":
+ HighlightType = true;
+ if (gColorObj.HighlightColor)
+ gColor = gColorObj.HighlightColor;
+ break;
+ default:
+ // Any other type will change some kind of text,
+ TextType = true;
+ tmpColor = gColorObj.TextColor;
+ if (tmpColor && tmpColor.toLowerCase() != "windowtext")
+ gColor = gColorObj.TextColor;
+ break;
+ }
+
+ // Set initial color in input field and in the colorpicker
+ SetCurrentColor(gColor);
+ gDialog.ColorPicker.initColor(gColor);
+
+ // Use last-picked colors passed in, or those persistent on dialog
+ if (TextType)
+ {
+ if ( !("LastTextColor" in gColorObj) || !gColorObj.LastTextColor)
+ gColorObj.LastTextColor = gDialog.LastPickedColor.getAttribute("LastTextColor");
+ LastPickedColor = gColorObj.LastTextColor;
+ }
+ else if (HighlightType)
+ {
+ if ( !("LastHighlightColor" in gColorObj) || !gColorObj.LastHighlightColor)
+ gColorObj.LastHighlightColor = gDialog.LastPickedColor.getAttribute("LastHighlightColor");
+ LastPickedColor = gColorObj.LastHighlightColor;
+ }
+ else
+ {
+ if ( !("LastBackgroundColor" in gColorObj) || !gColorObj.LastBackgroundColor)
+ gColorObj.LastBackgroundColor = gDialog.LastPickedColor.getAttribute("LastBackgroundColor");
+ LastPickedColor = gColorObj.LastBackgroundColor;
+ }
+
+ // Set method to detect clicking on OK button
+ // so we don't get fooled by changing "default" behavior
+ gDialog.Ok.setAttribute("onclick", "SetDefaultToOk()");
+
+ if (!LastPickedColor) {
+ // Hide the button, as there is no last color available.
+ gDialog.LastPickedButton.hidden = true;
+ } else {
+ gDialog.LastPickedColor.setAttribute("style", "background-color: " + LastPickedColor);
+
+ // Make "Last-picked" the default button, until the user selects a color.
+ gDialog.Ok.removeAttribute("default");
+ gDialog.LastPickedButton.setAttribute("default", "true");
+ }
+
+ // Caller can prevent user from submitting an empty, i.e., default color
+ NoDefault = gColorObj.NoDefault;
+ if (NoDefault)
+ {
+ // Hide the "Default button -- user must pick a color
+ document.getElementById("DefaultColorButton").collapsed = true;
+ }
+
+ // Set focus to colorpicker if not set to table radio buttons above
+ if (!haveTableRadio)
+ gDialog.ColorPicker.focus();
+
+ SetWindowLocation();
+}
+
+function ChangePalette(palette)
+{
+ gDialog.ColorPicker.setAttribute("palettename", palette);
+ window.sizeToContent();
+}
+
+function SelectColor()
+{
+ var color = gDialog.ColorPicker.color;
+ if (color)
+ SetCurrentColor(color);
+}
+
+function RemoveColor()
+{
+ SetCurrentColor("");
+ gDialog.ColorInput.focus();
+ SetDefaultToOk();
+}
+
+function SelectColorByKeypress(aEvent)
+{
+ if (aEvent.charCode == aEvent.DOM_VK_SPACE)
+ {
+ SelectColor();
+ SetDefaultToOk();
+ }
+}
+
+function SelectLastPickedColor()
+{
+ SetCurrentColor(LastPickedColor);
+ if ( onAccept() )
+ //window.close();
+ return true;
+
+ return false;
+}
+
+function SetCurrentColor(color)
+{
+ // TODO: Validate color?
+ if(!color) color = "";
+ gColor = TrimString(color).toLowerCase();
+ if (gColor == "mixed")
+ gColor = "";
+ gDialog.ColorInput.value = gColor;
+ SetColorSwatch();
+}
+
+function SetColorSwatch()
+{
+ // TODO: DON'T ALLOW SPACES?
+ var color = TrimString(gDialog.ColorInput.value);
+ if (color)
+ {
+ gDialog.ColorSwatch.setAttribute("style",("background-color:"+color));
+ gDialog.ColorSwatch.removeAttribute("default");
+ }
+ else
+ {
+ gDialog.ColorSwatch.setAttribute("style",("background-color:inherit"));
+ gDialog.ColorSwatch.setAttribute("default","true");
+ }
+}
+
+function SetDefaultToOk()
+{
+ gDialog.LastPickedButton.removeAttribute("default");
+ gDialog.Ok.setAttribute("default","true");
+ LastPickedIsDefault = false;
+}
+
+function ValidateData()
+{
+ if (LastPickedIsDefault)
+ gColor = LastPickedColor;
+ else
+ gColor = gDialog.ColorInput.value;
+
+ gColor = TrimString(gColor).toLowerCase();
+
+ // TODO: Validate the color string!
+
+ if (NoDefault && !gColor)
+ {
+ ShowInputErrorMessage(GetString("NoColorError"));
+ SetTextboxFocus(gDialog.ColorInput);
+ return false;
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (!ValidateData())
+ return false;
+
+ // Set return values and save in persistent color attributes
+ if (TextType)
+ {
+ gColorObj.TextColor = gColor;
+ if (gColor.length > 0)
+ {
+ gDialog.LastPickedColor.setAttribute("LastTextColor", gColor);
+ gColorObj.LastTextColor = gColor;
+ }
+ }
+ else if (HighlightType)
+ {
+ gColorObj.HighlightColor = gColor;
+ if (gColor.length > 0)
+ {
+ gDialog.LastPickedColor.setAttribute("LastHighlightColor", gColor);
+ gColorObj.LastHighlightColor = gColor;
+ }
+ }
+ else
+ {
+ gColorObj.BackgroundColor = gColor;
+ if (gColor.length > 0)
+ {
+ gDialog.LastPickedColor.setAttribute("LastBackgroundColor", gColor);
+ gColorObj.LastBackgroundColor = gColor;
+ }
+ // If table or cell requested, tell caller which element to set on
+ if (TableOrCell && gDialog.TableRadio.selected)
+ gColorObj.Type = "Table";
+ }
+ SaveWindowLocation();
+
+ return true; // do close the window
+}
+
+function onCancelColor()
+{
+ // Tells caller that user canceled
+ gColorObj.Cancel = true;
+ SaveWindowLocation();
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdColorPicker.xul
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdColorPicker.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancelColor();">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdColorPicker.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <hbox id="TableOrCellGroup" align="center" collapsed="true">
+ <label control="CellOrTableGroup" value="&background.label;" accesskey="&background.accessKey;"/>
+ <radiogroup id="CellOrTableGroup" orient="horizontal">
+ <radio id="TableRadio" label="&table.label;" accesskey="&table.accessKey;"/>
+ <radio id="CellRadio" label="&cell.label;" accesskey="&cell.accessKey;"/>
+ </radiogroup>
+ </hbox>
+ <colorpicker id="ColorPicker" palettename="standard"
+ persist="palettename"
+ onclick="SetDefaultToOk();"
+ ondblclick="if (onAccept()) window.close();"
+ onkeypress="SelectColorByKeypress(event);"
+ onselect="SelectColor();"/>
+<!-- Web palette is not implemented???
+ <hbox align="center">
+ <label value="&palette.label;"/>
+ <radio id="StandardPalette" label="&standardPalette.label;" oncommand="ChangePalette('standard')"/>
+ <radio id="WebPalette" label="&webPalette.label;" oncommand="ChangePalette('web')"/>
+ </hbox>
+-->
+ <spacer class="spacer"/>
+ <vbox flex="1">
+ <button id="LastPickedButton" crop="right" oncommand="SelectLastPickedColor();">
+ <spacer id="LastPickedColor"
+ LastTextColor="" LastBackgroundColor=""
+ persist="LastTextColor LastBackgroundColor"/>
+ <label value="&lastPickedColor.label;" accesskey="&lastPickedColor.accessKey;" flex="1" style="text-align: center;"/>
+ </button>
+ <label value="&setColor1.label;"/>
+ <label value="&setColor2.label;" accesskey="&setColor2.accessKey;" control="ColorInput"/>
+ <label value="&setColorExample.label;"/>
+ <hbox align="center" flex="1=">
+ <textbox id="ColorInput" style="width: 8em" oninput="SetColorSwatch(); SetDefaultToOk();"/>
+ <spacer flex="1"/>
+ <spacer id="ColorPickerSwatch"/>
+ <spacer flex="1"/>
+ <button id="DefaultColorButton" label="&default.label;" accesskey="&default.accessKey;"
+ style="margin-right:0px;" oncommand="RemoveColor()"/>
+ </hbox>
+ </vbox>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdColorProps.js
@@ -0,0 +1,450 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Behavior notes:
+ Radio buttons select "UseDefaultColors" vs. "UseCustomColors" modes.
+ If any color attribute is set in the body, mode is "Custom Colors",
+ even if 1 or more (but not all) are actually null (= "use default")
+ When in "Custom Colors" mode, all colors will be set on body tag,
+ even if they are just default colors, to assure compatable colors in page.
+ User cannot select "use default" for individual colors
+*/
+
+//Cancel() is in EdDialogCommon.js
+
+var gBodyElement;
+var prefs;
+var gBackgroundImage;
+
+// Initialize in case we can't get them from prefs???
+var defaultTextColor="#000000";
+var defaultLinkColor="#000099";
+var defaultActiveColor="#000099";
+var defaultVisitedColor="#990099";
+var defaultBackgroundColor="#FFFFFF";
+const styleStr = "style";
+const textStr = "text";
+const linkStr = "link";
+const vlinkStr = "vlink";
+const alinkStr = "alink";
+const bgcolorStr = "bgcolor";
+const backgroundStr = "background";
+const cssColorStr = "color";
+const cssBackgroundColorStr = "background-color";
+const cssBackgroundImageStr = "background-image";
+const colorStyle = cssColorStr + ": ";
+const backColorStyle = cssBackgroundColorStr + ": ";
+const backImageStyle = "; " + cssBackgroundImageStr + ": url(";
+
+var customTextColor;
+var customLinkColor;
+var customActiveColor;
+var customVisitedColor;
+var customBackgroundColor;
+var previewBGColor;
+var gHaveDocumentUrl = false;
+
+// dialog initialization code
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ gDialog.ColorPreview = document.getElementById("ColorPreview");
+ gDialog.NormalText = document.getElementById("NormalText");
+ gDialog.LinkText = document.getElementById("LinkText");
+ gDialog.ActiveLinkText = document.getElementById("ActiveLinkText");
+ gDialog.VisitedLinkText = document.getElementById("VisitedLinkText");
+ gDialog.PageColorGroup = document.getElementById("PageColorGroup");
+ gDialog.DefaultColorsRadio = document.getElementById("DefaultColorsRadio");
+ gDialog.CustomColorsRadio = document.getElementById("CustomColorsRadio");
+ gDialog.BackgroundImageInput = document.getElementById("BackgroundImageInput");
+
+ try {
+ gBodyElement = editor.rootElement;
+ } catch (e) {}
+
+ if (!gBodyElement)
+ {
+ dump("Failed to get BODY element!\n");
+ window.close();
+ }
+
+ // Set element we will edit
+ globalElement = gBodyElement.cloneNode(false);
+
+ // Initialize default colors from browser prefs
+ var browserColors = GetDefaultBrowserColors();
+ if (browserColors)
+ {
+ // Use author's browser pref colors passed into dialog
+ defaultTextColor = browserColors.TextColor;
+ defaultLinkColor = browserColors.LinkColor;
+ defaultActiveColor = browserColors.ActiveLinkColor;
+ defaultVisitedColor = browserColors.VisitedLinkColor;
+ defaultBackgroundColor= browserColors.BackgroundColor;
+ }
+
+ // We only need to test for this once per dialog load
+ gHaveDocumentUrl = GetDocumentBaseUrl();
+
+ InitDialog();
+
+ gDialog.PageColorGroup.focus();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ // Get image from document
+ gBackgroundImage = GetHTMLOrCSSStyleValue(globalElement, backgroundStr, cssBackgroundImageStr);
+ if (/url\((.*)\)/.test( gBackgroundImage ))
+ gBackgroundImage = RegExp.$1;
+
+ gDialog.BackgroundImageInput.value = gBackgroundImage;
+
+ if (gBackgroundImage)
+ gDialog.ColorPreview.setAttribute(styleStr, backImageStyle+gBackgroundImage+");");
+
+ SetRelativeCheckbox();
+
+ customTextColor = GetHTMLOrCSSStyleValue(globalElement, textStr, cssColorStr);
+ customTextColor = ConvertRGBColorIntoHEXColor(customTextColor);
+ customLinkColor = globalElement.getAttribute(linkStr);
+ customActiveColor = globalElement.getAttribute(alinkStr);
+ customVisitedColor = globalElement.getAttribute(vlinkStr);
+ customBackgroundColor = GetHTMLOrCSSStyleValue(globalElement, bgcolorStr, cssBackgroundColorStr);
+ customBackgroundColor = ConvertRGBColorIntoHEXColor(customBackgroundColor);
+
+ var haveCustomColor =
+ customTextColor ||
+ customLinkColor ||
+ customVisitedColor ||
+ customActiveColor ||
+ customBackgroundColor;
+
+ // Set default color explicitly for any that are missing
+ // PROBLEM: We are using "windowtext" and "window" for the Windows OS
+ // default color values. This works with CSS in preview window,
+ // but we should NOT use these as values for HTML attributes!
+
+ if (!customTextColor) customTextColor = defaultTextColor;
+ if (!customLinkColor) customLinkColor = defaultLinkColor;
+ if (!customActiveColor) customActiveColor = defaultActiveColor;
+ if (!customVisitedColor) customVisitedColor = defaultVisitedColor;
+ if (!customBackgroundColor) customBackgroundColor = defaultBackgroundColor;
+
+ if (haveCustomColor)
+ {
+ // If any colors are set, then check the "Custom" radio button
+ gDialog.PageColorGroup.selectedItem = gDialog.CustomColorsRadio;
+ UseCustomColors();
+ }
+ else
+ {
+ gDialog.PageColorGroup.selectedItem = gDialog.DefaultColorsRadio;
+ UseDefaultColors();
+ }
+}
+
+function GetColorAndUpdate(ColorWellID)
+{
+ // Only allow selecting when in custom mode
+ if (!gDialog.CustomColorsRadio.selected) return;
+
+ var colorWell = document.getElementById(ColorWellID);
+ if (!colorWell) return;
+
+ // Don't allow a blank color, i.e., using the "default"
+ var colorObj = { NoDefault:true, Type:"", TextColor:0, PageColor:0, Cancel:false };
+
+ switch( ColorWellID )
+ {
+ case "textCW":
+ colorObj.Type = "Text";
+ colorObj.TextColor = customTextColor;
+ break;
+ case "linkCW":
+ colorObj.Type = "Link";
+ colorObj.TextColor = customLinkColor;
+ break;
+ case "activeCW":
+ colorObj.Type = "ActiveLink";
+ colorObj.TextColor = customActiveColor;
+ break;
+ case "visitedCW":
+ colorObj.Type = "VisitedLink";
+ colorObj.TextColor = customVisitedColor;
+ break;
+ case "backgroundCW":
+ colorObj.Type = "Page";
+ colorObj.PageColor = customBackgroundColor;
+ break;
+ }
+
+ window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
+
+ // User canceled the dialog
+ if (colorObj.Cancel)
+ return;
+
+ var color = "";
+ switch( ColorWellID )
+ {
+ case "textCW":
+ color = customTextColor = colorObj.TextColor;
+ break;
+ case "linkCW":
+ color = customLinkColor = colorObj.TextColor;
+ break;
+ case "activeCW":
+ color = customActiveColor = colorObj.TextColor;
+ break;
+ case "visitedCW":
+ color = customVisitedColor = colorObj.TextColor;
+ break;
+ case "backgroundCW":
+ color = customBackgroundColor = colorObj.BackgroundColor;
+ break;
+ }
+
+ setColorWell(ColorWellID, color);
+ SetColorPreview(ColorWellID, color);
+}
+
+function SetColorPreview(ColorWellID, color)
+{
+ switch( ColorWellID )
+ {
+ case "textCW":
+ gDialog.NormalText.setAttribute(styleStr,colorStyle+color);
+ break;
+ case "linkCW":
+ gDialog.LinkText.setAttribute(styleStr,colorStyle+color);
+ break;
+ case "activeCW":
+ gDialog.ActiveLinkText.setAttribute(styleStr,colorStyle+color);
+ break;
+ case "visitedCW":
+ gDialog.VisitedLinkText.setAttribute(styleStr,colorStyle+color);
+ break;
+ case "backgroundCW":
+ // Must combine background color and image style values
+ var styleValue = backColorStyle+color;
+ if (gBackgroundImage)
+ styleValue += ";"+backImageStyle+gBackgroundImage+");";
+
+ gDialog.ColorPreview.setAttribute(styleStr,styleValue);
+ previewBGColor = color;
+ break;
+ }
+}
+
+function UseCustomColors()
+{
+ SetElementEnabledById("TextButton", true);
+ SetElementEnabledById("LinkButton", true);
+ SetElementEnabledById("ActiveLinkButton", true);
+ SetElementEnabledById("VisitedLinkButton", true);
+ SetElementEnabledById("BackgroundButton", true);
+ SetElementEnabledById("Text", true);
+ SetElementEnabledById("Link", true);
+ SetElementEnabledById("Active", true);
+ SetElementEnabledById("Visited", true);
+ SetElementEnabledById("Background", true);
+
+ SetColorPreview("textCW", customTextColor);
+ SetColorPreview("linkCW", customLinkColor);
+ SetColorPreview("activeCW", customActiveColor);
+ SetColorPreview("visitedCW", customVisitedColor);
+ SetColorPreview("backgroundCW", customBackgroundColor);
+
+ setColorWell("textCW", customTextColor);
+ setColorWell("linkCW", customLinkColor);
+ setColorWell("activeCW", customActiveColor);
+ setColorWell("visitedCW", customVisitedColor);
+ setColorWell("backgroundCW", customBackgroundColor);
+}
+
+function UseDefaultColors()
+{
+ SetColorPreview("textCW", defaultTextColor);
+ SetColorPreview("linkCW", defaultLinkColor);
+ SetColorPreview("activeCW", defaultActiveColor);
+ SetColorPreview("visitedCW", defaultVisitedColor);
+ SetColorPreview("backgroundCW", defaultBackgroundColor);
+
+ // Setting to blank color will remove color from buttons,
+ setColorWell("textCW", "");
+ setColorWell("linkCW", "");
+ setColorWell("activeCW", "");
+ setColorWell("visitedCW", "");
+ setColorWell("backgroundCW", "");
+
+ // Disable color buttons and labels
+ SetElementEnabledById("TextButton", false);
+ SetElementEnabledById("LinkButton", false);
+ SetElementEnabledById("ActiveLinkButton", false);
+ SetElementEnabledById("VisitedLinkButton", false);
+ SetElementEnabledById("BackgroundButton", false);
+ SetElementEnabledById("Text", false);
+ SetElementEnabledById("Link", false);
+ SetElementEnabledById("Active", false);
+ SetElementEnabledById("Visited", false);
+ SetElementEnabledById("Background", false);
+}
+
+function chooseFile()
+{
+ // Get a local image file, converted into URL format
+ var fileName = GetLocalFileURL("img");
+ if (fileName)
+ {
+ // Always try to relativize local file URLs
+ if (gHaveDocumentUrl)
+ fileName = MakeRelativeUrl(fileName);
+
+ gDialog.BackgroundImageInput.value = fileName;
+
+ SetRelativeCheckbox();
+
+ ValidateAndPreviewImage(true);
+ }
+ SetTextboxFocus(gDialog.BackgroundImageInput);
+}
+
+function ChangeBackgroundImage()
+{
+ // Don't show error message for image while user is typing
+ ValidateAndPreviewImage(false);
+ SetRelativeCheckbox();
+}
+
+function ValidateAndPreviewImage(ShowErrorMessage)
+{
+ // First make a string with just background color
+ var styleValue = backColorStyle+previewBGColor+";";
+
+ var retVal = true;
+ var image = TrimString(gDialog.BackgroundImageInput.value);
+ if (image)
+ {
+ gBackgroundImage = image;
+
+ // Display must use absolute URL if possible
+ var displayImage = gHaveDocumentUrl ? MakeAbsoluteUrl(image) : image;
+ styleValue += backImageStyle+displayImage+");";
+ }
+ else gBackgroundImage = null;
+
+ // Set style on preview (removes image if not valid)
+ gDialog.ColorPreview.setAttribute(styleStr, styleValue);
+
+ // Note that an "empty" string is valid
+ return retVal;
+}
+
+function ValidateData()
+{
+ var editor = GetCurrentEditor();
+ try {
+ // Colors values are updated as they are picked, no validation necessary
+ if (gDialog.DefaultColorsRadio.selected)
+ {
+ editor.removeAttributeOrEquivalent(globalElement, textStr, true);
+ globalElement.removeAttribute(linkStr);
+ globalElement.removeAttribute(vlinkStr);
+ globalElement.removeAttribute(alinkStr);
+ editor.removeAttributeOrEquivalent(globalElement, bgcolorStr, true);
+ }
+ else
+ {
+ //Do NOT accept the CSS "WindowsOS" color strings!
+ // Problem: We really should try to get the actual color values
+ // from windows, but I don't know how to do that!
+ var tmpColor = customTextColor.toLowerCase();
+ if (tmpColor != "windowtext")
+ editor.setAttributeOrEquivalent(globalElement, textStr,
+ customTextColor, true);
+ else
+ editor.removeAttributeOrEquivalent(globalElement, textStr, true);
+
+ tmpColor = customBackgroundColor.toLowerCase();
+ if (tmpColor != "window")
+ editor.setAttributeOrEquivalent(globalElement, bgcolorStr, customBackgroundColor, true);
+ else
+ editor.removeAttributeOrEquivalent(globalElement, bgcolorStr, true);
+
+ globalElement.setAttribute(linkStr, customLinkColor);
+ globalElement.setAttribute(vlinkStr, customVisitedColor);
+ globalElement.setAttribute(alinkStr, customActiveColor);
+ }
+
+ if (ValidateAndPreviewImage(true))
+ {
+ // A valid image may be null for no image
+ if (gBackgroundImage)
+ globalElement.setAttribute(backgroundStr, gBackgroundImage);
+ else
+ editor.removeAttributeOrEquivalent(globalElement, backgroundStr, true);
+
+ return true;
+ }
+ } catch (e) {}
+ return false;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ // Copy attributes to element we are changing
+ try {
+ GetCurrentEditor().cloneAttributes(gBodyElement, globalElement);
+ } catch (e) {}
+
+ SaveWindowLocation();
+ return true; // do close the window
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdColorProps.xul
@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorColorProperties.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdColorProps.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <groupbox align="start">
+ <caption label="&pageColors.label;"/>
+ <radiogroup id="PageColorGroup">
+ <radio id="DefaultColorsRadio" label="&defaultColorsRadio.label;" oncommand="UseDefaultColors()"
+ accesskey="&defaultColorsRadio.accessKey;"
+ tooltiptext="&defaultColorsRadio.tooltip;" />
+ <radio id="CustomColorsRadio" label="&customColorsRadio.label;" oncommand="UseCustomColors()"
+ accesskey="&customColorsRadio.accessKey;"
+ tooltiptext="&customColorsRadio.tooltip;" />
+ </radiogroup>
+ <hbox class="indent">
+ <grid>
+ <columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label id="Text" control="TextButton"
+ value="&normalText.label;&colon.character;"
+ accesskey="&normalText.accessKey;"/>
+ <button id="TextButton" class="color-button" oncommand="GetColorAndUpdate('textCW');">
+ <spacer id="textCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="Link" control="LinkButton"
+ value="&linkText.label;&colon.character;"
+ accesskey="&linkText.accessKey;"/>
+ <button id="LinkButton" class="color-button" oncommand="GetColorAndUpdate('linkCW');">
+ <spacer id="linkCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="Active" control="ActiveLinkButton"
+ value="&activeLinkText.label;&colon.character;"
+ accesskey="&activeLinkText.accessKey;"/>
+ <button id="ActiveLinkButton" class="color-button" oncommand="GetColorAndUpdate('activeCW');">
+ <spacer id="activeCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="Visited" control="VisitedLinkButton"
+ value="&visitedLinkText.label;&colon.character;"
+ accesskey="&visitedLinkText.accessKey;"/>
+ <button id="VisitedLinkButton" class="color-button" oncommand="GetColorAndUpdate('visitedCW');">
+ <spacer id="visitedCW" class="color-well"/>
+ </button>
+ </row>
+ <row align="center">
+ <label id="Background" control="BackgroundButton"
+ value="&background.label;"
+ accesskey="&background.accessKey;"/>
+ <button id="BackgroundButton" class="color-button" oncommand="GetColorAndUpdate('backgroundCW');">
+ <spacer id="backgroundCW" class="color-well"/>
+ </button>
+ </row>
+ </rows>
+ </grid>
+ <vbox id="ColorPreview" flex="1">
+ <spacer flex="1"/>
+ <label class="larger" id="NormalText" value="&normalText.label;"/>
+ <spacer flex="1"/>
+ <label class="larger" id="LinkText" value="&linkText.label;"/>
+ <spacer flex="1"/>
+ <label class="larger" id="ActiveLinkText" value="&activeLinkText.label;"/>
+ <spacer flex="1"/>
+ <label class="larger" id="VisitedLinkText" value="&visitedLinkText.label;"/>
+ <spacer flex="1"/>
+ </vbox>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer class="spacer"/>
+ </groupbox>
+ <spacer class="spacer"/>
+ <label control="BackgroundImageInput"
+ value="&backgroundImage.label;"
+ accesskey="&backgroundImage.accessKey;"/>
+ <textbox id="BackgroundImageInput" class="uri-element" oninput="ChangeBackgroundImage()"
+ tooltiptext="&backgroundImage.tooltip;" flex="1"/>
+ <hbox align="center">
+ <!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
+ <checkbox id="MakeRelativeCheckbox" for="BackgroundImageInput"/>
+ <spacer flex="1"/>
+ <!-- from EdDialogOverlay.xul -->
+ <button id="ChooseFile"/>
+ </hbox>
+ <spacer class="smallspacer"/>
+ <hbox>
+ <spacer flex="1"/>
+ <!-- from EdDialogOverlay.xul -->
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdConvertToTable.js
@@ -0,0 +1,365 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gIndex;
+var gCommaIndex = "0";
+var gSpaceIndex = "1";
+var gOtherIndex = "2";
+
+// dialog initialization code
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+
+ gDialog.sepRadioGroup = document.getElementById("SepRadioGroup");
+ gDialog.sepCharacterInput = document.getElementById("SepCharacterInput");
+ gDialog.deleteSepCharacter = document.getElementById("DeleteSepCharacter");
+ gDialog.collapseSpaces = document.getElementById("CollapseSpaces");
+
+ // We persist the user's separator character
+ gDialog.sepCharacterInput.value = gDialog.sepRadioGroup.getAttribute("character");
+
+ gIndex = gDialog.sepRadioGroup.getAttribute("index");
+
+ switch (gIndex)
+ {
+ case gCommaIndex:
+ default:
+ gDialog.sepRadioGroup.selectedItem = document.getElementById("comma");
+ break;
+ case gSpaceIndex:
+ gDialog.sepRadioGroup.selectedItem = document.getElementById("space");
+ break;
+ case gOtherIndex:
+ gDialog.sepRadioGroup.selectedItem = document.getElementById("other");
+ break;
+ }
+
+ // Set initial enable state on character input and "collapse" checkbox
+ SelectCharacter(gIndex);
+
+ SetWindowLocation();
+}
+
+function InputSepCharacter()
+{
+ var str = gDialog.sepCharacterInput.value;
+
+ // Limit input to 1 character
+ if (str.length > 1)
+ str = str.slice(0,1);
+
+ // We can never allow tag or entity delimiters for separator character
+ if (str == "<" || str == ">" || str == "&" || str == ";" || str == " ")
+ str = "";
+
+ gDialog.sepCharacterInput.value = str;
+}
+
+function SelectCharacter(radioGroupIndex)
+{
+ gIndex = radioGroupIndex;
+ SetElementEnabledById("SepCharacterInput", gIndex == gOtherIndex);
+ SetElementEnabledById("CollapseSpaces", gIndex == gSpaceIndex);
+}
+
+function onAccept()
+{
+ var sepCharacter = "";
+ switch ( gIndex )
+ {
+ case gCommaIndex:
+ sepCharacter = ",";
+ break;
+ case gSpaceIndex:
+ sepCharacter = " ";
+ break;
+ case gOtherIndex:
+ sepCharacter = gDialog.sepCharacterInput.value.slice(0,1);
+ break;
+ }
+
+ var editor = GetCurrentEditor();
+ var str;
+ try {
+ str = editor.outputToString("text/html", kOutputLFLineBreak | kOutputSelectionOnly);
+ } catch (e) {}
+ if (!str)
+ {
+ SaveWindowLocation();
+ return true;
+ }
+
+ // Replace nbsp with spaces:
+ str = str.replace(/\u00a0/g, " ");
+
+ // Strip out </p> completely
+ str = str.replace(/\s*<\/p>\s*/g, "");
+
+ // Trim whitespace adjacent to <p> and <br> tags
+ // and replace <p> with <br>
+ // (which will be replaced with </tr> below)
+ str = str.replace(/\s*<p>\s*|\s*<br>\s*/g, "<br>");
+
+ // Trim leading <br>s
+ str = str.replace(/^(<br>)+/, "");
+
+ // Trim trailing <br>s
+ str = str.replace(/(<br>)+$/, "");
+
+ // Reduce multiple internal <br> to just 1
+ // TODO: Maybe add a checkbox to let user decide
+ //str = str.replace(/(<br>)+/g, "<br>");
+
+ // Trim leading and trailing spaces
+ str = str.replace(/^\s+|\s+$/, "");
+
+ // Remove all tag contents so we don't replace
+ // separator character within tags
+ // Also converts lists to something usefull
+ var stack = [];
+ var start;
+ var end;
+ var searchStart = 0;
+ var listSeparator = "";
+ var listItemSeparator = "";
+ var endList = false;
+
+ do {
+ start = str.indexOf("<", searchStart);
+
+ if (start >= 0)
+ {
+ end = str.indexOf(">", start+1);
+ if (end > start)
+ {
+ var tagContent = TrimString(str.slice(start+1, end));
+
+ if ( /^ol|^ul|^dl/.test(tagContent) )
+ {
+ // Replace list tag with <BR> to start new row
+ // at begining of second or greater list tag
+ str = str.slice(0, start) + listSeparator + str.slice(end+1);
+ if (listSeparator == "")
+ listSeparator = "<br>";
+
+ // Reset for list item separation into cells
+ listItemSeparator = "";
+ }
+ else if ( /^li|^dt|^dd/.test(tagContent) )
+ {
+ // Start a new row if this is first item after the ending the last list
+ if (endList)
+ listItemSeparator = "<br>";
+
+ // Start new cell at begining of second or greater list items
+ str = str.slice(0, start) + listItemSeparator + str.slice(end+1);
+
+ if (endList || listItemSeparator == "")
+ listItemSeparator = sepCharacter;
+
+ endList = false;
+ }
+ else
+ {
+ // Find end tags
+ endList = /^\/ol|^\/ul|^\/dl/.test(tagContent);
+ if ( endList || /^\/li|^\/dt|^\/dd/.test(tagContent) )
+ {
+ // Strip out tag
+ str = str.slice(0, start) + str.slice(end+1);
+ }
+ else
+ {
+ // Not a list-related tag: Store tag contents in an array
+ stack.push(tagContent);
+
+ // Keep the "<" and ">" while removing from source string
+ start++;
+ str = str.slice(0, start) + str.slice(end);
+ }
+ }
+ }
+ searchStart = start + 1;
+ }
+ } while (start >= 0);
+
+ // Replace separator characters with table cells
+ var replaceString;
+ if (gDialog.deleteSepCharacter.checked)
+ {
+ replaceString = "";
+ }
+ else
+ {
+ // Don't delete separator character,
+ // so include it at start of string to replace
+ replaceString = sepCharacter;
+ }
+
+ replaceString += "<td>";
+
+ if (sepCharacter.length > 0)
+ {
+ var tempStr = sepCharacter;
+ var regExpChars = ".!@#$%^&*-+[]{}()\|\\\/";
+ if (regExpChars.indexOf(sepCharacter) >= 0)
+ tempStr = "\\" + sepCharacter;
+
+ if (gIndex == gSpaceIndex)
+ {
+ // If checkbox is checked,
+ // one or more adjacent spaces are one separator
+ if (gDialog.collapseSpaces.checked)
+ tempStr = "\\s+"
+ else
+ tempStr = "\\s";
+ }
+ var pattern = new RegExp(tempStr, "g");
+ str = str.replace(pattern, replaceString);
+ }
+
+ // Put back tag contents that we removed above
+ searchStart = 0;
+ var stackIndex = 0;
+ do {
+ start = str.indexOf("<", searchStart);
+ end = start + 1;
+ if (start >= 0 && str.charAt(end) == ">")
+ {
+ // We really need a FIFO stack!
+ str = str.slice(0, end) + stack[stackIndex++] + str.slice(end);
+ }
+ searchStart = end;
+
+ } while (start >= 0);
+
+ // End table row and start another for each br or p
+ str = str.replace(/\s*<br>\s*/g, "</tr>\n<tr><td>");
+
+ // Add the table tags and the opening and closing tr/td tags
+ // Default table attributes should be same as those used in nsHTMLEditor::CreateElementWithDefaults()
+ // (Default width="100%" is used in EdInsertTable.js)
+ str = "<table border=\"1\" width=\"100%\" cellpadding=\"2\" cellspacing=\"2\">\n<tr><td>" + str + "</tr>\n</table>\n";
+
+ editor.beginTransaction();
+
+ // Delete the selection -- makes it easier to find where table will insert
+ var nodeBeforeTable = null;
+ var nodeAfterTable = null;
+ try {
+ editor.deleteSelection(0);
+
+ var anchorNodeBeforeInsert = editor.selection.anchorNode;
+ var offset = editor.selection.anchorOffset;
+ if (anchorNodeBeforeInsert.nodeType == Node.TEXT_NODE)
+ {
+ // Text was split. Table should be right after the first or before
+ nodeBeforeTable = anchorNodeBeforeInsert.previousSibling;
+ nodeAfterTable = anchorNodeBeforeInsert;
+ }
+ else
+ {
+ // Table should be inserted right after node pointed to by selection
+ if (offset > 0)
+ nodeBeforeTable = anchorNodeBeforeInsert.childNodes.item(offset - 1);
+
+ nodeAfterTable = anchorNodeBeforeInsert.childNodes.item(offset);
+ }
+
+ editor.insertHTML(str);
+ } catch (e) {}
+
+ var table = null;
+ if (nodeAfterTable)
+ {
+ var previous = nodeAfterTable.previousSibling;
+ if (previous && previous.nodeName.toLowerCase() == "table")
+ table = previous;
+ }
+ if (!table && nodeBeforeTable)
+ {
+ var next = nodeBeforeTable.nextSibling;
+ if (next && next.nodeName.toLowerCase() == "table")
+ table = next;
+ }
+
+ if (table)
+ {
+ // Fixup table only if pref is set
+ var prefs = GetPrefs();
+ var firstRow;
+ try {
+ if (prefs && prefs.getBoolPref("editor.table.maintain_structure") )
+ editor.normalizeTable(table);
+
+ firstRow = editor.getFirstRow(table);
+ } catch(e) {}
+
+ // Put caret in first cell
+ if (firstRow)
+ {
+ var node2 = firstRow.firstChild;
+ do {
+ if (node2.nodeName.toLowerCase() == "td" ||
+ node2.nodeName.toLowerCase() == "th")
+ {
+ try {
+ editor.selection.collapse(node2, 0);
+ } catch(e) {}
+ break;
+ }
+ node2 = node.nextSibling;
+ } while (node2);
+ }
+ }
+
+ editor.endTransaction();
+
+ // Save persisted attributes
+ gDialog.sepRadioGroup.setAttribute("index", gIndex);
+ if (gIndex == gOtherIndex)
+ gDialog.sepRadioGroup.setAttribute("character", sepCharacter);
+
+ SaveWindowLocation();
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdConvertToTable.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdConvertToTable.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();"
+ style="min-width:20em">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <!--- Element-specific methods -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdConvertToTable.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <description class="wrap" flex="1">&instructions1.label;</description>
+ <description class="wrap" flex="1">&instructions2.label;</description>
+ <radiogroup id="SepRadioGroup" persist="index character" index="0" character="">
+ <radio id="comma" label="&commaRadio.label;" oncommand="SelectCharacter('0');"/>
+ <radio id="space" label="&spaceRadio.label;" oncommand="SelectCharacter('1');"/>
+ <hbox>
+ <spacer class="radio-spacer"/>
+ <checkbox id="CollapseSpaces" label="&collapseSpaces.label;"
+ checked="true" persist="checked"
+ tooltiptext="&collapseSpaces.tooltip;"/>
+ </hbox>
+ <hbox align="center">
+ <radio id="other" label="&otherRadio.label;" oncommand="SelectCharacter('2');"/>
+ <textbox class="narrow" id="SepCharacterInput" oninput="InputSepCharacter()"/>
+ </hbox>
+ </radiogroup>
+ <spacer class="spacer"/>
+ <checkbox id="DeleteSepCharacter" label="&deleteCharCheck.label;" persist="checked"/>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDialogCommon.js
@@ -0,0 +1,1090 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pete Collins
+ * Brian King
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Each editor window must include this file
+
+// Object to attach commonly-used widgets (all dialogs should use this)
+var gDialog = {};
+
+var gValidationError = false;
+
+// Use for 'defaultIndex' param in InitPixelOrPercentMenulist
+const gPixel = 0;
+const gPercent = 1;
+
+const gMaxPixels = 100000; // Used for image size, borders, spacing, and padding
+// Gecko code uses 1000 for maximum rowspan, colspan
+// Also, editing performance is really bad above this
+const gMaxRows = 1000;
+const gMaxColumns = 1000;
+const gMaxTableSize = 1000000; // Width or height of table or cells
+
+// For dialogs that expand in size. Default is smaller size see "onMoreFewer()" below
+var SeeMore = false;
+
+// A XUL element with id="location" for managing
+// dialog location relative to parent window
+var gLocation;
+
+// The element being edited - so AdvancedEdit can have access to it
+var globalElement;
+
+/* Validate contents of an input field
+ *
+ * inputWidget The 'textbox' XUL element for text input of the attribute's value
+ * listWidget The 'menulist' XUL element for choosing "pixel" or "percent"
+ * May be null when no pixel/percent is used.
+ * minVal minimum allowed for input widget's value
+ * maxVal maximum allowed for input widget's value
+ * (when "listWidget" is used, maxVal is used for "pixel" maximum,
+ * 100% is assumed if "percent" is the user's choice)
+ * element The DOM element that we set the attribute on. May be null.
+ * attName Name of the attribute to set. May be null or ignored if "element" is null
+ * mustHaveValue If true, error dialog is displayed if "value" is empty string
+ *
+ * This calls "ValidateNumberRange()", which puts up an error dialog to inform the user.
+ * If error, we also:
+ * Shift focus and select contents of the inputWidget,
+ * Switch to appropriate panel of tabbed dialog if user implements "SwitchToValidate()",
+ * and/or will expand the dialog to full size if "More / Fewer" feature is implemented
+ *
+ * Returns the "value" as a string, or "" if error or input contents are empty
+ * The global "gValidationError" variable is set true if error was found
+ */
+function ValidateNumber(inputWidget, listWidget, minVal, maxVal, element, attName, mustHaveValue, mustShowMoreSection)
+{
+ if (!inputWidget)
+ {
+ gValidationError = true;
+ return "";
+ }
+
+ // Global error return value
+ gValidationError = false;
+ var maxLimit = maxVal;
+ var isPercent = false;
+
+ var numString = TrimString(inputWidget.value);
+ if (numString || mustHaveValue)
+ {
+ if (listWidget)
+ isPercent = (listWidget.selectedIndex == 1);
+ if (isPercent)
+ maxLimit = 100;
+
+ // This method puts up the error message
+ numString = ValidateNumberRange(numString, minVal, maxLimit, mustHaveValue);
+ if(!numString)
+ {
+ // Switch to appropriate panel for error reporting
+ SwitchToValidatePanel();
+
+ // or expand dialog for users of "More / Fewer" button
+ if ("dialog" in window && dialog &&
+ "MoreSection" in gDialog && gDialog.MoreSection)
+ {
+ if ( !SeeMore )
+ onMoreFewer();
+ }
+
+ // Error - shift to offending input widget
+ SetTextboxFocus(inputWidget);
+ gValidationError = true;
+ }
+ else
+ {
+ if (isPercent)
+ numString += "%";
+ if (element)
+ GetCurrentEditor().setAttributeOrEquivalent(element, attName, numString, true);
+ }
+ } else if (element) {
+ GetCurrentEditor().removeAttributeOrEquivalent(element, attName, true)
+ }
+ return numString;
+}
+
+/* Validate contents of an input field
+ *
+ * value number to validate
+ * minVal minimum allowed for input widget's value
+ * maxVal maximum allowed for input widget's value
+ * (when "listWidget" is used, maxVal is used for "pixel" maximum,
+ * 100% is assumed if "percent" is the user's choice)
+ * mustHaveValue If true, error dialog is displayed if "value" is empty string
+ *
+ * If inputWidget's value is outside of range, or is empty when "mustHaveValue" = true,
+ * an error dialog is popuped up to inform the user. The focus is shifted
+ * to the inputWidget.
+ *
+ * Returns the "value" as a string, or "" if error or input contents are empty
+ * The global "gValidationError" variable is set true if error was found
+ */
+function ValidateNumberRange(value, minValue, maxValue, mustHaveValue)
+{
+ // Initialize global error flag
+ gValidationError = false;
+ value = TrimString(String(value));
+
+ // We don't show error for empty string unless caller wants to
+ if (!value && !mustHaveValue)
+ return "";
+
+ var numberStr = "";
+
+ if (value.length > 0)
+ {
+ // Extract just numeric characters
+ var number = Number(value.replace(/\D+/g, ""));
+ if (number >= minValue && number <= maxValue )
+ {
+ // Return string version of the number
+ return String(number);
+ }
+ numberStr = String(number);
+ }
+
+ var message = "";
+
+ if (numberStr.length > 0)
+ {
+ // We have a number from user outside of allowed range
+ message = GetString( "ValidateRangeMsg");
+ message = message.replace(/%n%/, numberStr);
+ message += "\n ";
+ }
+ message += GetString( "ValidateNumberMsg");
+
+ // Replace variable placeholders in message with number values
+ message = message.replace(/%min%/, minValue).replace(/%max%/, maxValue);
+ ShowInputErrorMessage(message);
+
+ // Return an empty string to indicate error
+ gValidationError = true;
+ return "";
+}
+
+function SetTextboxFocusById(id)
+{
+ SetTextboxFocus(document.getElementById(id));
+}
+
+function SetTextboxFocus(textbox)
+{
+ if (textbox)
+ {
+ //XXX Using the setTimeout is hacky workaround for bug 103197
+ // Must create a new function to keep "textbox" in scope
+ setTimeout( function(textbox) { textbox.focus(); textbox.select(); }, 0, textbox );
+ }
+}
+
+function ShowInputErrorMessage(message)
+{
+ AlertWithTitle(GetString("InputError"), message);
+ window.focus();
+}
+
+// Get the text appropriate to parent container
+// to determine what a "%" value is referring to.
+// elementForAtt is element we are actually setting attributes on
+// (a temporary copy of element in the doc to allow canceling),
+// but elementInDoc is needed to find parent context in document
+function GetAppropriatePercentString(elementForAtt, elementInDoc)
+{
+ var editor = GetCurrentEditor();
+ try {
+ var name = elementForAtt.nodeName.toLowerCase();
+ if ( name == "td" || name == "th")
+ return GetString("PercentOfTable");
+
+ // Check if element is within a table cell
+ if (editor.getElementOrParentByTagName("td", elementInDoc))
+ return GetString("PercentOfCell");
+ else
+ return GetString("PercentOfWindow");
+ } catch (e) { return "";}
+}
+
+function ClearListbox(listbox)
+{
+ if (listbox)
+ {
+ listbox.clearSelection();
+ while (listbox.firstChild)
+ listbox.removeChild(listbox.firstChild);
+ }
+}
+
+function forceInteger(elementID)
+{
+ var editField = document.getElementById( elementID );
+ if ( !editField )
+ return;
+
+ var stringIn = editField.value;
+ if (stringIn && stringIn.length > 0)
+ {
+ // Strip out all nonnumeric characters
+ stringIn = stringIn.replace(/\D+/g,"");
+ if (!stringIn) stringIn = "";
+
+ // Write back only if changed
+ if (stringIn != editField.value)
+ editField.value = stringIn;
+ }
+}
+
+function InitPixelOrPercentMenulist(elementForAtt, elementInDoc, attribute, menulistID, defaultIndex)
+{
+ if (!defaultIndex) defaultIndex = gPixel;
+
+ // var size = elementForAtt.getAttribute(attribute);
+ var size = GetHTMLOrCSSStyleValue(elementForAtt, attribute, attribute)
+ var menulist = document.getElementById(menulistID);
+ var pixelItem;
+ var percentItem;
+
+ if (!menulist)
+ {
+ dump("NO MENULIST found for ID="+menulistID+"\n");
+ return size;
+ }
+
+ menulist.removeAllItems();
+ pixelItem = menulist.appendItem(GetString("Pixels"));
+
+ if (!pixelItem) return 0;
+
+ percentItem = menulist.appendItem(GetAppropriatePercentString(elementForAtt, elementInDoc));
+ if (size && size.length > 0)
+ {
+ // Search for a "%" or "px"
+ if (/%/.test(size))
+ {
+ // Strip out the %
+ size = RegExp.leftContext;
+ if (percentItem)
+ menulist.selectedItem = percentItem;
+ }
+ else
+ {
+ if (/px/.test(size))
+ // Strip out the px
+ size = RegExp.leftContext;
+ menulist.selectedItem = pixelItem;
+ }
+ }
+ else
+ menulist.selectedIndex = defaultIndex;
+
+ return size;
+}
+
+function onAdvancedEdit()
+{
+ // First validate data from widgets in the "simpler" property dialog
+ if (ValidateData())
+ {
+ // Set true if OK is clicked in the Advanced Edit dialog
+ window.AdvancedEditOK = false;
+ // Open the AdvancedEdit dialog, passing in the element to be edited
+ // (the copy named "globalElement")
+ window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank", "chrome,close,titlebar,modal,resizable=yes", "", globalElement);
+ window.focus();
+ if (window.AdvancedEditOK)
+ {
+ // Copy edited attributes to the dialog widgets:
+ InitDialog();
+ }
+ }
+}
+
+function getColor(ColorPickerID)
+{
+ var colorPicker = document.getElementById(ColorPickerID);
+ var color;
+ if (colorPicker)
+ {
+ // Extract color from colorPicker and assign to colorWell.
+ color = colorPicker.getAttribute("color");
+ if (color && color == "")
+ return null;
+ // Clear color so next if it's called again before
+ // color picker is actually used, we dedect the "don't set color" state
+ colorPicker.setAttribute("color","");
+ }
+
+ return color;
+}
+
+function setColorWell(ColorWellID, color)
+{
+ var colorWell = document.getElementById(ColorWellID);
+ if (colorWell)
+ {
+ if (!color || color == "")
+ {
+ // Don't set color (use default)
+ // Trigger change to not show color swatch
+ colorWell.setAttribute("default","true");
+ // Style in CSS sets "background-color",
+ // but color won't clear unless we do this:
+ colorWell.removeAttribute("style");
+ }
+ else
+ {
+ colorWell.removeAttribute("default");
+ // Use setAttribute so colorwell can be a XUL element, such as button
+ colorWell.setAttribute("style", "background-color:"+color);
+ }
+ }
+}
+
+function getColorAndSetColorWell(ColorPickerID, ColorWellID)
+{
+ var color = getColor(ColorPickerID);
+ setColorWell(ColorWellID, color);
+ return color;
+}
+
+function InitMoreFewer()
+{
+ // Set SeeMore bool to the OPPOSITE of the current state,
+ // which is automatically saved by using the 'persist="more"'
+ // attribute on the gDialog.MoreFewerButton button
+ // onMoreFewer will toggle it and redraw the dialog
+ SeeMore = (gDialog.MoreFewerButton.getAttribute("more") != "1");
+ onMoreFewer();
+ gDialog.MoreFewerButton.setAttribute("accesskey",GetString("PropertiesAccessKey"));
+}
+
+function onMoreFewer()
+{
+ if (SeeMore)
+ {
+ gDialog.MoreSection.collapsed = true;
+ gDialog.MoreFewerButton.setAttribute("more","0");
+ gDialog.MoreFewerButton.setAttribute("label",GetString("MoreProperties"));
+ SeeMore = false;
+ }
+ else
+ {
+ gDialog.MoreSection.collapsed = false;
+ gDialog.MoreFewerButton.setAttribute("more","1");
+ gDialog.MoreFewerButton.setAttribute("label",GetString("FewerProperties"));
+ SeeMore = true;
+ }
+ window.sizeToContent();
+}
+
+function SwitchToValidatePanel()
+{
+ // no default implementation
+ // Only EdTableProps.js currently implements this
+}
+
+const nsIFilePicker = Components.interfaces.nsIFilePicker;
+
+function GetLocalFileURL(filterType)
+{
+ var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ var fileType = "html";
+
+ if (filterType == "img")
+ {
+ fp.init(window, GetString("SelectImageFile"), nsIFilePicker.modeOpen);
+ fp.appendFilters(nsIFilePicker.filterImages);
+ fileType = "image";
+ }
+ // Current usage of this is in Link dialog,
+ // where we always want HTML first
+ else if (filterType.indexOf("html") == 0)
+ {
+ fp.init(window, GetString("OpenHTMLFile"), nsIFilePicker.modeOpen);
+
+ // When loading into Composer, direct user to prefer HTML files and text files,
+ // so we call separately to control the order of the filter list
+ fp.appendFilters(nsIFilePicker.filterHTML);
+ fp.appendFilters(nsIFilePicker.filterText);
+
+ // Link dialog also allows linking to images
+ if (filterType.indexOf("img") > 0)
+ fp.appendFilters(nsIFilePicker.filterImages);
+
+ }
+ // Default or last filter is "All Files"
+ fp.appendFilters(nsIFilePicker.filterAll);
+
+ // set the file picker's current directory to last-opened location saved in prefs
+ SetFilePickerDirectory(fp, fileType);
+
+
+ /* doesn't handle *.shtml files */
+ try {
+ var ret = fp.show();
+ if (ret == nsIFilePicker.returnCancel)
+ return null;
+ }
+ catch (ex) {
+ dump("filePicker.chooseInputFile threw an exception\n");
+ return null;
+ }
+ SaveFilePickerDirectory(fp, fileType);
+
+ var fileHandler = GetFileProtocolHandler();
+ return fp.file ? fileHandler.getURLSpecFromFile(fp.file) : null;
+}
+
+function GetMetaElement(name)
+{
+ if (name)
+ {
+ name = name.toLowerCase();
+ if (name != "")
+ {
+ var editor = GetCurrentEditor();
+ try {
+ var metaNodes = editor.document.getElementsByTagName("meta");
+ for (var i = 0; i < metaNodes.length; i++)
+ {
+ var metaNode = metaNodes.item(i);
+ if (metaNode && metaNode.getAttribute("name") == name)
+ return metaNode;
+ }
+ } catch (e) {}
+ }
+ }
+ return null;
+}
+
+function CreateMetaElement(name)
+{
+ var editor = GetCurrentEditor();
+ try {
+ var metaElement = editor.createElementWithDefaults("meta");
+ metaElement.setAttribute("name", name);
+ return metaElement;
+ } catch (e) {}
+
+ return null;
+}
+
+function GetHTTPEquivMetaElement(name)
+{
+ if (name)
+ {
+ name = name.toLowerCase();
+ if (name != "")
+ {
+ var editor = GetCurrentEditor();
+ try {
+ var metaNodes = editor.document.getElementsByTagName("meta");
+ for (var i = 0; i < metaNodes.length; i++)
+ {
+ var metaNode = metaNodes.item(i);
+ if (metaNode)
+ {
+ var httpEquiv = metaNode.getAttribute("http-equiv");
+ if (httpEquiv && httpEquiv.toLowerCase() == name)
+ return metaNode;
+ }
+ }
+ } catch (e) {}
+ }
+ }
+ return null;
+}
+
+function CreateHTTPEquivMetaElement(name)
+{
+ var editor = GetCurrentEditor();
+ try {
+ var metaElement = editor.createElementWithDefaults("meta");
+ metaElement.setAttribute("http-equiv", name);
+ return metaElement;
+ } catch (e) {}
+
+ return null;
+}
+
+function CreateHTTPEquivElement(name)
+{
+ var editor = GetCurrentEditor();
+ try {
+ var metaElement = editor.createElementWithDefaults("meta");
+ metaElement.setAttribute("http-equiv", name);
+ return metaElement;
+ } catch (e) {}
+
+ return null;
+}
+
+// Change "content" attribute on a META element,
+// or delete entire element it if content is empty
+// This uses undoable editor transactions
+function SetMetaElementContent(metaElement, content, insertNew, prepend)
+{
+ if (metaElement)
+ {
+ var editor = GetCurrentEditor();
+ try {
+ if(!content || content == "")
+ {
+ if (!insertNew)
+ editor.deleteNode(metaElement);
+ }
+ else
+ {
+ if (insertNew)
+ {
+ metaElement.setAttribute("content", content);
+ if (prepend)
+ PrependHeadElement(metaElement);
+ else
+ AppendHeadElement(metaElement);
+ }
+ else
+ editor.setAttribute(metaElement, "content", content);
+ }
+ } catch (e) {}
+ }
+}
+
+function GetHeadElement()
+{
+ var editor = GetCurrentEditor();
+ try {
+ var headList = editor.document.getElementsByTagName("head");
+ return headList.item(0);
+ } catch (e) {}
+
+ return null;
+}
+
+function PrependHeadElement(element)
+{
+ var head = GetHeadElement();
+ if (head)
+ {
+ var editor = GetCurrentEditor();
+ try {
+ // Use editor's undoable transaction
+ // Last param "true" says "don't change the selection"
+ editor.insertNode(element, head, 0, true);
+ } catch (e) {}
+ }
+}
+
+function AppendHeadElement(element)
+{
+ var head = GetHeadElement();
+ if (head)
+ {
+ var position = 0;
+ if (head.hasChildNodes())
+ position = head.childNodes.length;
+
+ var editor = GetCurrentEditor();
+ try {
+ // Use editor's undoable transaction
+ // Last param "true" says "don't change the selection"
+ editor.insertNode(element, head, position, true);
+ } catch (e) {}
+ }
+}
+
+function SetWindowLocation()
+{
+ gLocation = document.getElementById("location");
+ if (gLocation)
+ {
+ window.screenX = Math.max(0, Math.min(window.opener.screenX + Number(gLocation.getAttribute("offsetX")),
+ screen.availWidth - window.outerWidth));
+ window.screenY = Math.max(0, Math.min(window.opener.screenY + Number(gLocation.getAttribute("offsetY")),
+ screen.availHeight - window.outerHeight));
+ }
+}
+
+function SaveWindowLocation()
+{
+ if (gLocation)
+ {
+ var newOffsetX = window.screenX - window.opener.screenX;
+ var newOffsetY = window.screenY - window.opener.screenY;
+ gLocation.setAttribute("offsetX", window.screenX - window.opener.screenX);
+ gLocation.setAttribute("offsetY", window.screenY - window.opener.screenY);
+ }
+}
+
+function onCancel()
+{
+ SaveWindowLocation();
+ // Close dialog by returning true
+ return true;
+}
+
+function SetRelativeCheckbox(checkbox)
+{
+ if (!checkbox) {
+ checkbox = document.getElementById("MakeRelativeCheckbox");
+ if (!checkbox)
+ return;
+ }
+
+ var editor = GetCurrentEditor();
+ // Mail never allows relative URLs, so hide the checkbox
+ if (editor && (editor.flags & Components.interfaces.nsIPlaintextEditor.eEditorMailMask))
+ {
+ checkbox.collapsed = true;
+ return;
+ }
+
+ var input = document.getElementById(checkbox.getAttribute("for"));
+ if (!input)
+ return;
+
+ var url = TrimString(input.value);
+ var urlScheme = GetScheme(url);
+
+ // Check it if url is relative (no scheme).
+ checkbox.checked = url.length > 0 && !urlScheme;
+
+ // Now do checkbox enabling:
+ var enable = false;
+
+ var docUrl = GetDocumentBaseUrl();
+ var docScheme = GetScheme(docUrl);
+
+ if (url && docUrl && docScheme)
+ {
+ if (urlScheme)
+ {
+ // Url is absolute
+ // If we can make a relative URL, then enable must be true!
+ // (this lets the smarts of MakeRelativeUrl do all the hard work)
+ enable = (GetScheme(MakeRelativeUrl(url)).length == 0);
+ }
+ else
+ {
+ // Url is relative
+ // Check if url is a named anchor
+ // but document doesn't have a filename
+ // (it's probably "index.html" or "index.htm",
+ // but we don't want to allow a malformed URL)
+ if (url[0] == "#")
+ {
+ var docFilename = GetFilename(docUrl);
+ enable = docFilename.length > 0;
+ }
+ else
+ {
+ // Any other url is assumed
+ // to be ok to try to make absolute
+ enable = true;
+ }
+ }
+ }
+
+ SetElementEnabled(checkbox, enable);
+}
+
+// oncommand handler for the Relativize checkbox in EditorOverlay.xul
+function MakeInputValueRelativeOrAbsolute(checkbox)
+{
+ var input = document.getElementById(checkbox.getAttribute("for"));
+ if (!input)
+ return;
+
+ var docUrl = GetDocumentBaseUrl();
+ if (!docUrl)
+ {
+ // Checkbox should be disabled if not saved,
+ // but keep this error message in case we change that
+ AlertWithTitle("", GetString("SaveToUseRelativeUrl"));
+ window.focus();
+ }
+ else
+ {
+ // Note that "checked" is opposite of its last state,
+ // which determines what we want to do here
+ if (checkbox.checked)
+ input.value = MakeRelativeUrl(input.value);
+ else
+ input.value = MakeAbsoluteUrl(input.value);
+
+ // Reset checkbox to reflect url state
+ SetRelativeCheckbox(checkbox);
+ }
+}
+
+var IsBlockParent = {
+ APPLET: true,
+ BLOCKQUOTE: true,
+ BODY: true,
+ CENTER: true,
+ DD: true,
+ DIV: true,
+ FORM: true,
+ LI: true,
+ NOSCRIPT: true,
+ OBJECT: true,
+ TD: true,
+ TH: true
+};
+
+var NotAnInlineParent = {
+ COL: true,
+ COLGROUP: true,
+ DL: true,
+ DIR: true,
+ MENU: true,
+ OL: true,
+ TABLE: true,
+ TBODY: true,
+ TFOOT: true,
+ THEAD: true,
+ TR: true,
+ UL: true
+};
+
+function nodeIsBreak(editor, node)
+{
+ return !node || node.localName == 'BR' || editor.nodeIsBlock(node);
+}
+
+function InsertElementAroundSelection(element)
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ // First get the selection as a single range
+ var range, start, end, offset;
+ var count = editor.selection.rangeCount;
+ if (count == 1)
+ range = editor.selection.getRangeAt(0).cloneRange();
+ else
+ {
+ range = editor.document.createRange();
+ start = editor.selection.getRangeAt(0)
+ range.setStart(start.startContainer, start.startOffset);
+ end = editor.selection.getRangeAt(--count);
+ range.setEnd(end.endContainer, end.endOffset);
+ }
+
+ // Flatten the selection to child nodes of the common ancestor
+ while (range.startContainer != range.commonAncestorContainer)
+ range.setStartBefore(range.startContainer);
+ while (range.endContainer != range.commonAncestorContainer)
+ range.setEndAfter(range.endContainer);
+
+ if (editor.nodeIsBlock(element))
+ // Block element parent must be a valid block
+ while (!(range.commonAncestorContainer.localName in IsBlockParent))
+ range.selectNode(range.commonAncestorContainer);
+ else
+ {
+ // Fail if we're not inserting a block (use setInlineProperty instead)
+ if (!nodeIsBreak(editor, range.commonAncestorContainer))
+ return false;
+ else if (range.commonAncestorContainer.localName in NotAnInlineParent)
+ // Inline element parent must not be an invalid block
+ do range.selectNode(range.commonAncestorContainer);
+ while (range.commonAncestorContainer.localName in NotAnInlineParent);
+ else
+ // Further insert block check
+ for (var i = range.startOffset; ; i++)
+ if (i == range.endOffset)
+ return false;
+ else if (nodeIsBreak(editor, range.commonAncestorContainer.childNodes[i]))
+ break;
+ }
+
+ // The range may be contained by body text, which should all be selected.
+ offset = range.startOffset;
+ start = range.startContainer.childNodes[offset];
+ if (!nodeIsBreak(editor, start))
+ {
+ while (!nodeIsBreak(editor, start.previousSibling))
+ {
+ start = start.previousSibling;
+ offset--;
+ }
+ }
+ end = range.endContainer.childNodes[range.endOffset];
+ if (end && !nodeIsBreak(editor, end.previousSibling))
+ {
+ while (!nodeIsBreak(editor, end))
+ end = end.nextSibling;
+ }
+
+ // Now insert the node
+ editor.insertNode(element, range.commonAncestorContainer, offset, true);
+ offset = element.childNodes.length;
+ if (!editor.nodeIsBlock(element))
+ editor.setShouldTxnSetSelection(false);
+
+ // Move all the old child nodes to the element
+ var empty = true;
+ while (start != end)
+ {
+ var next = start.nextSibling;
+ editor.deleteNode(start);
+ editor.insertNode(start, element, element.childNodes.length);
+ empty = false;
+ start = next;
+ }
+ if (!editor.nodeIsBlock(element))
+ editor.setShouldTxnSetSelection(true);
+ else
+ {
+ // Also move a trailing <br>
+ if (start && start.localName == 'BR')
+ {
+ editor.deleteNode(start);
+ editor.insertNode(start, element, element.childNodes.length);
+ empty = false;
+ }
+ // Still nothing? Insert a <br> so the node is not empty
+ if (empty)
+ editor.insertNode(editor.createElementWithDefaults("br"), element, element.childNodes.length);
+
+ // Hack to set the selection just inside the element
+ editor.insertNode(editor.document.createTextNode(""), element, offset);
+ }
+ }
+ finally {
+ editor.endTransaction();
+ }
+
+ return true;
+}
+
+function nodeIsBlank(node)
+{
+ return node && node.nodeType == Node.TEXT_NODE && !/\S/.test(node.data);
+}
+
+function nodeBeginsBlock(editor, node)
+{
+ while (nodeIsBlank(node))
+ node = node.nextSibling;
+ return nodeIsBreak(editor, node);
+}
+
+function nodeEndsBlock(editor, node)
+{
+ while (nodeIsBlank(node))
+ node = node.previousSibling;
+ return nodeIsBreak(editor, node);
+}
+
+// C++ function isn't exposed to JS :-(
+function RemoveBlockContainer(element)
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ var range = editor.document.createRange();
+ range.selectNode(element);
+ var offset = range.startOffset;
+ var parent = element.parentNode;
+
+ // May need to insert a break after the removed element
+ if (!nodeBeginsBlock(editor, element.nextSibling) &&
+ !nodeEndsBlock(editor, element.lastChild))
+ editor.insertNode(editor.createElementWithDefaults("br"), parent, range.endOffset);
+
+ // May need to insert a break before the removed element, or if it was empty
+ if (!nodeEndsBlock(editor, element.previousSibling) &&
+ !nodeBeginsBlock(editor, element.firstChild || element.nextSibling))
+ editor.insertNode(editor.createElementWithDefaults("br"), parent, offset++);
+
+ // Now remove the element
+ editor.deleteNode(element);
+
+ // Need to copy the contained nodes?
+ for (var i = 0; i < element.childNodes.length; i++)
+ editor.insertNode(element.childNodes[i].cloneNode(true), parent, offset++);
+ }
+ finally {
+ editor.endTransaction();
+ }
+}
+
+// C++ function isn't exposed to JS :-(
+function RemoveContainer(element)
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ var range = editor.document.createRange();
+ var parent = element.parentNode;
+ // Allow for automatic joining of text nodes
+ // so we can't delete the container yet
+ // so we need to copy the contained nodes
+ for (var i = 0; i < element.childNodes.length; i++) {
+ range.selectNode(element);
+ editor.insertNode(element.childNodes[i].cloneNode(true), parent, range.startOffset);
+ }
+ // Now remove the element
+ editor.deleteNode(element);
+ }
+ finally {
+ editor.endTransaction();
+ }
+}
+
+function FillLinkMenulist(linkMenulist, headingsArray)
+{
+ var menupopup = linkMenulist.firstChild;
+ var editor = GetCurrentEditor();
+ try {
+ var treeWalker = editor.document.createTreeWalker(editor.document, 1, null, true);
+ var headingList = [];
+ var anchorList = []; // for sorting
+ var anchorMap = {}; // for weeding out duplicates and making heading anchors unique
+ var anchor;
+ var i;
+ for (var element = treeWalker.nextNode(); element; element = treeWalker.nextNode())
+ {
+ // grab headings
+ // Skip headings that already have a named anchor as their first child
+ // (this may miss nearby anchors, but at least we don't insert another
+ // under the same heading)
+ if (element instanceof HTMLHeadingElement && element.textContent &&
+ !(element.firstChild instanceof HTMLAnchorElement && element.firstChild.name))
+ headingList.push(element);
+
+ // grab named anchors
+ if (element instanceof HTMLAnchorElement && element.name)
+ {
+ anchor = '#' + element.name;
+ if (!(anchor in anchorMap))
+ {
+ anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
+ anchorMap[anchor] = true;
+ }
+ }
+
+ // grab IDs
+ if (element.id)
+ {
+ anchor = '#' + element.id;
+ if (!(anchor in anchorMap))
+ {
+ anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
+ anchorMap[anchor] = true;
+ }
+ }
+ }
+ // add anchor for headings
+ for (i = 0; i < headingList.length; i++)
+ {
+ var heading = headingList[i];
+
+ // Use just first 40 characters, don't add "...",
+ // and replace whitespace with "_" and strip non-word characters
+ anchor = '#' + ConvertToCDATAString(TruncateStringAtWordEnd(heading.textContent, 40, false));
+
+ // Append "_" to any name already in the list
+ while (anchor in anchorMap)
+ anchor += "_";
+ anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
+ anchorMap[anchor] = true;
+
+ // Save nodes in an array so we can create anchor node under it later
+ headingsArray[anchor] = heading;
+ }
+ if (anchorList.length)
+ {
+ // case insensitive sort
+ function compare(a, b)
+ {
+ if(a.sortkey < b.sortkey) return -1;
+ if(a.sortkey > b.sortkey) return 1;
+ return 0;
+ }
+ anchorList.sort(compare);
+
+ for (i = 0; i < anchorList.length; i++)
+ createMenuItem(menupopup,anchorList[i].anchor);
+ }
+ else
+ {
+ var item = createMenuItem(menupopup, GetString("NoNamedAnchorsOrHeadings"));
+ item.setAttribute("disabled", "true");
+ }
+ } catch (e) {}
+}
+
+function createMenuItem(aMenuPopup, aLabel)
+{
+ var menuitem = document.createElement("menuitem");
+ menuitem.setAttribute("label", aLabel);
+ aMenuPopup.appendChild(menuitem);
+ return menuitem;
+}
+
+// Shared by Image and Link dialogs for the "Choose" button for links
+function chooseLinkFile()
+{
+ // Get a local file, converted into URL format
+ var fileName = GetLocalFileURL("html, img");
+ if (fileName)
+ {
+ // Always try to relativize local file URLs
+ if (gHaveDocumentUrl)
+ fileName = MakeRelativeUrl(fileName);
+
+ gDialog.hrefInput.value = fileName;
+
+ // Do stuff specific to a particular dialog
+ // (This is defined separately in Image and Link dialogs)
+ ChangeLinkLocation();
+ }
+ // Put focus into the input field
+ SetTextboxFocus(gDialog.hrefInput);
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDialogOverlay.xul
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/EdDialogOverlay.dtd">
+
+<overlay id="EdDialogOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<vbox id="AdvancedEdit">
+ <hbox flex="1" style="margin-top: 0.2em" align="center">
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton1" oncommand="onAdvancedEdit()" label="&AdvancedEditButton.label;"
+ accesskey="&AdvancedEditButton.accessKey;" tooltiptext="&AdvancedEditButton.tooltip;"/>
+ </hbox>
+ <separator class="groove"/>
+</vbox>
+
+<!-- Extra buttons to use when just button is needed
+ E.g. Image Properties Dialog switches position between 2 locations
+ Placed here to use same attributes as AdvancedEditButton button
+-->
+<button
+ id = "AdvancedEditButton"
+ oncommand = "onAdvancedEdit();"
+ label = "&AdvancedEditButton.label;"
+ accesskey = "&AdvancedEditButton.accessKey;"
+ tooltiptext="&AdvancedEditButton.tooltip;"/>
+
+<button
+ id = "AdvancedEditButton2"
+ oncommand = "onAdvancedEdit()"
+ label = "&AdvancedEditButton.label;"
+ accesskey = "&AdvancedEditButton.accessKey;"
+ tooltiptext="&AdvancedEditButton.tooltip;"/>
+
+<button
+ id = "ChooseFile"
+ oncommand = "chooseFile()"
+ label = "&chooseFileButton.label;"
+ accesskey = "&chooseFileButton.accessKey;"/>
+
+<checkbox
+ id = "MakeRelativeCheckbox"
+ label = "&makeUrlRelative.label;"
+ accesskey = "&makeUrlRelative.accessKey;"
+ oncommand = "MakeInputValueRelativeOrAbsolute(this);"
+ tooltiptext = "&makeUrlRelative.tooltip;"/>
+
+<vbox id="LinkLocationBox">
+ <label control="hrefInput" accesskey="&LinkURLEditField.accessKey;" width="1">&LinkURLEditField.label;</label>
+ <textbox id="hrefInput" type="autocomplete"
+ autocompletesearch="history" timeout="50" maxrows="6"
+ disablehistory="false" class="uri-element"
+ oninput="ChangeLinkLocation();">
+ <menupopup class="autocomplete-history-popup"
+ popupalign="topleft" popupanchor="bottomleft"
+ oncommand="this.parentNode.value = event.target.getAttribute('label'); ChangeLinkLocation();"/>
+ </textbox>
+ <hbox align="center">
+ <!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
+ <checkbox id="MakeRelativeLink"
+ for="hrefInput"
+ label="&makeUrlRelative.label;"
+ accesskey="&makeUrlRelative.accessKey;"
+ oncommand="MakeInputValueRelativeOrAbsolute(this);"
+ tooltiptext="&makeUrlRelative.tooltip;"/>
+ <spacer flex="1"/>
+ <button label="&chooseFileLinkButton.label;" accesskey="&chooseFileLinkButton.accessKey;" oncommand="chooseLinkFile();"/>
+ </hbox>
+</vbox>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDialogTemplate.js
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+//Cancel() is in EdDialogCommon.js
+var insertNew = true;
+var tagname = "TAG NAME"
+
+// dialog initialization code
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+ // gDialog is declared in EdDialogCommon.js
+ // Set commonly-used widgets like this:
+ gDialog.fooButton = document.getElementById("fooButton");
+
+ initDialog();
+
+ // Set window location relative to parent window (based on persisted attributes)
+ SetWindowLocation();
+
+ // Set focus to first widget in dialog, e.g.:
+ SetTextboxFocus(gDialog.fooButton);
+}
+
+function InitDialog()
+{
+ // Initialize all dialog widgets here,
+ // e.g., get attributes from an element for property dialog
+}
+
+function onAccept()
+{
+ // Validate all user data and set attributes and possibly insert new element here
+ // If there's an error the user must correct, return false to keep dialog open.
+
+ SaveWindowLocation();
+ return true; // do close the window
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDialogTemplate.xul
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/Ed?????????.dtd">
+<!-- dialog containing a control requiring initial setup -->
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/Ed?????.js"/>
+ <script type="application/x-javascript" src="chrome://global/content/dialogOverlay.js" />
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDictionary.js
@@ -0,0 +1,216 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gSpellChecker;
+var gWordToAdd;
+
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+ // Get the SpellChecker shell
+ if ("gSpellChecker" in window.opener && window.opener.gSpellChecker)
+ gSpellChecker = window.opener.gSpellChecker;
+
+ if (!gSpellChecker)
+ {
+ dump("SpellChecker not found!!!\n");
+ window.close();
+ return;
+ }
+ // The word to add word is passed as the 2nd extra parameter in window.openDialog()
+ gWordToAdd = window.arguments[1];
+
+ gDialog.WordInput = document.getElementById("WordInput");
+ gDialog.DictionaryList = document.getElementById("DictionaryList");
+
+ gDialog.WordInput.value = gWordToAdd;
+ FillDictionaryList();
+
+ // Select the supplied word if it is already in the list
+ SelectWordToAddInList();
+ SetTextboxFocus(gDialog.WordInput);
+}
+
+function ValidateWordToAdd()
+{
+ gWordToAdd = TrimString(gDialog.WordInput.value);
+ if (gWordToAdd.length > 0)
+ {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function SelectWordToAddInList()
+{
+ for (var i = 0; i < gDialog.DictionaryList.getRowCount(); i++)
+ {
+
+ var wordInList = gDialog.DictionaryList.getItemAtIndex(i);
+ if (wordInList && gWordToAdd == wordInList.label)
+ {
+ gDialog.DictionaryList.selectedIndex = i;
+ break;
+ }
+ }
+}
+
+function AddWord()
+{
+ if (ValidateWordToAdd())
+ {
+ try {
+ gSpellChecker.AddWordToDictionary(gWordToAdd);
+ }
+ catch (e) {
+ dump("Exception occured in gSpellChecker.AddWordToDictionary\nWord to add probably already existed\n");
+ }
+
+ // Rebuild the dialog list
+ FillDictionaryList();
+
+ SelectWordToAddInList();
+ gDialog.WordInput.value = "";
+ }
+}
+
+function ReplaceWord()
+{
+ if (ValidateWordToAdd())
+ {
+ var selItem = gDialog.DictionaryList.selectedItem;
+ if (selItem)
+ {
+ try {
+ gSpellChecker.RemoveWordFromDictionary(selItem.label);
+ } catch (e) {}
+
+ try {
+ // Add to the dictionary list
+ gSpellChecker.AddWordToDictionary(gWordToAdd);
+
+ // Just change the text on the selected item
+ // instead of rebuilding the list
+ selItem.label = gWordToAdd;
+ } catch (e) {
+ // Rebuild list and select the word - it was probably already in the list
+ dump("Exception occured adding word in ReplaceWord\n");
+ FillDictionaryList();
+ SelectWordToAddInList();
+ }
+ }
+ }
+}
+
+function RemoveWord()
+{
+ var selIndex = gDialog.DictionaryList.selectedIndex;
+ if (selIndex >= 0)
+ {
+ var word = gDialog.DictionaryList.selectedItem.label;
+
+ // Remove word from list
+ gDialog.DictionaryList.removeItemAt(selIndex);
+
+ // Remove from dictionary
+ try {
+ //Not working: BUG 43348
+ gSpellChecker.RemoveWordFromDictionary(word);
+ }
+ catch (e)
+ {
+ dump("Failed to remove word from dictionary\n");
+ }
+
+ ResetSelectedItem(selIndex);
+ }
+}
+
+function FillDictionaryList()
+{
+ var selIndex = gDialog.DictionaryList.selectedIndex;
+
+ // Clear the current contents of the list
+ ClearListbox(gDialog.DictionaryList);
+
+ // Get the list from the spell checker
+ gSpellChecker.GetPersonalDictionary()
+
+ var haveList = false;
+
+ // Get words until an empty string is returned
+ do {
+ var word = gSpellChecker.GetPersonalDictionaryWord();
+ if (word != "")
+ {
+ gDialog.DictionaryList.appendItem(word, "");
+ haveList = true;
+ }
+ } while (word != "");
+
+ //XXX: BUG 74467: If list is empty, it doesn't layout to full height correctly
+ // (ignores "rows" attribute) (bug is latered, so we are fixing here for now)
+ if (!haveList)
+ gDialog.DictionaryList.appendItem("", "");
+
+ ResetSelectedItem(selIndex);
+}
+
+function ResetSelectedItem(index)
+{
+ var lastIndex = gDialog.DictionaryList.getRowCount() - 1;
+ if (index > lastIndex)
+ index = lastIndex;
+
+ // If we didn't have a selected item,
+ // set it to the first item
+ if (index == -1 && lastIndex >= 0)
+ index = 0;
+
+ gDialog.DictionaryList.selectedIndex = index;
+}
+
+function onClose()
+{
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdDictionary.xul
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPersonalDictionary.dtd">
+<dialog buttons="cancel" title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ persist="screenX screenY"
+ onload = "Startup()"
+ ondialogcancel="return onClose();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDictionary.js"/>
+
+ <broadcaster id="args" value=""/>
+ <grid>
+ <columns><column style="width: 15em" flex="1"/><column flex="1"/></columns>
+ <rows>
+ <row>
+ <label value="&wordEditField.label;"
+ control="WordInput"
+ accesskey="&wordEditField.accessKey;"/>
+ <spacer/>
+ </row>
+ <row>
+ <textbox id="WordInput" flex="1"/>
+ <button id="AddWord" oncommand="AddWord()" label="&AddButton.label;"
+ accesskey="&AddButton.accessKey;"/>
+ </row>
+ <row>
+ <label value="&DictionaryList.label;"
+ control="DictionaryList"
+ accesskey="&DictionaryList.accessKey;"/>
+ <spacer/>
+ </row>
+ <row>
+ <listbox rows="8" id="DictionaryList" flex="1"/>
+ <vbox flex="1">
+ <button id="ReplaceWord" oncommand="ReplaceWord()" label="&ReplaceButton.label;"
+ accesskey="&ReplaceButton.accessKey;"/>
+ <spacer class="spacer"/>
+ <button id="RemoveWord" oncommand="RemoveWord()" label="&RemoveButton.label;"
+ accesskey="&RemoveButton.accessKey;"/>
+ <spacer class="spacer"/>
+ <spacer flex="1"/>
+ <button dlgtype="cancel" class="exit-dialog" id="close" label="&CloseButton.label;"
+ default="true" oncommand="onClose();"
+ accesskey="&CloseButton.accessKey;"/>
+ </vbox>
+ </row>
+ </rows>
+ </grid>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdFieldSetProps.js
@@ -0,0 +1,218 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Field Set Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var insertNew;
+var fieldsetElement;
+var newLegend;
+var legendElement;
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ gDialog.editText = document.getElementById("EditText");
+ gDialog.legendText = document.getElementById("LegendText");
+ gDialog.legendAlign = document.getElementById("LegendAlign");
+ gDialog.RemoveFieldSet = document.getElementById("RemoveFieldSet");
+
+ // Get a single selected field set element
+ const kTagName = "fieldset";
+ try {
+ // Find a selected fieldset, or if one is at start or end of selection.
+ fieldsetElement = editor.getSelectedElement(kTagName);
+ if (!fieldsetElement)
+ fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
+ if (!fieldsetElement)
+ fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
+ } catch (e) {}
+
+ if (fieldsetElement)
+ // We found an element and don't need to insert one
+ insertNew = false;
+ else
+ {
+ insertNew = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ fieldsetElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
+
+ if (!fieldsetElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ // Hide button removing existing fieldset
+ gDialog.RemoveFieldSet.hidden = true;
+ }
+
+ legendElement = fieldsetElement.firstChild;
+ if (legendElement && legendElement.localName == "LEGEND")
+ {
+ newLegend = false;
+ var range = editor.document.createRange();
+ range.selectNode(legendElement);
+ gDialog.legendText.value = range.toString();
+ if (/</.test(legendElement.innerHTML))
+ {
+ gDialog.editText.checked = false;
+ gDialog.editText.disabled = false;
+ gDialog.legendText.disabled = true;
+ gDialog.editText.addEventListener("command", onEditText, false);
+ gDialog.RemoveFieldSet.focus();
+ }
+ else
+ SetTextboxFocus(gDialog.legendText);
+ }
+ else
+ {
+ newLegend = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+
+ legendElement = editor.createElementWithDefaults("legend");
+ if (!legendElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ SetTextboxFocus(gDialog.legendText);
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = legendElement.cloneNode(false);
+
+ InitDialog();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ gDialog.legendAlign.value = GetHTMLOrCSSStyleValue(globalElement, "align", "caption-side");
+}
+
+function onEditText()
+{
+ gDialog.editText.removeEventListener("command", onEditText, false);
+ AlertWithTitle(GetString("Alert"), GetString("EditTextWarning"));
+}
+
+function RemoveFieldSet()
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+ try {
+ if (!newLegend)
+ editor.deleteNode(legendElement);
+ RemoveBlockContainer(fieldsetElement);
+ } finally {
+ editor.endTransaction();
+ }
+ SaveWindowLocation();
+ window.close();
+}
+
+function ValidateData()
+{
+ if (gDialog.legendAlign.value)
+ globalElement.setAttribute("align", gDialog.legendAlign.value);
+ else
+ globalElement.removeAttribute("align");
+ return true;
+}
+
+function onAccept()
+{
+ // All values are valid - copy to actual element in doc
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ editor.beginTransaction();
+
+ try {
+ editor.cloneAttributes(legendElement, globalElement);
+
+ if (insertNew)
+ {
+ if (gDialog.legendText.value)
+ {
+ fieldsetElement.appendChild(legendElement);
+ legendElement.appendChild(editor.document.createTextNode(gDialog.legendText.value));
+ }
+ InsertElementAroundSelection(fieldsetElement);
+ }
+ else if (gDialog.editText.checked)
+ {
+ editor.setShouldTxnSetSelection(false);
+
+ if (gDialog.legendText.value)
+ {
+ if (newLegend)
+ editor.insertNode(legendElement, fieldsetElement, 0, true);
+ else while (legendElement.firstChild)
+ editor.deleteNode(legendElement.lastChild);
+ editor.insertNode(editor.document.createTextNode(gDialog.legendText.value), legendElement, 0);
+ }
+ else if (!newLegend)
+ editor.deleteNode(legendElement);
+
+ editor.setShouldTxnSetSelection(true);
+ }
+ }
+ finally {
+ editor.endTransaction();
+ }
+
+ SaveWindowLocation();
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdFieldSetProps.xul
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Field Set Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorFieldSetProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdFieldSetProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&Legend.label;" accesskey="&Legend.accesskey;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <checkbox id="EditText" label="&EditLegendText.label;" accesskey="&EditLegendText.accesskey;" checked="true" disabled="true"
+ oncommand="gDialog.legendText.disabled = !gDialog.editText.checked;"/>
+ <textbox id="LegendText" accesskey="&Legend.accesskey;"/>
+ </row>
+ <row align="center">
+ <label control="LegendAlign" value="&LegendAlign.label;" accesskey="&LegendAlign.accesskey;"/>
+ <menulist id="LegendAlign">
+ <menupopup>
+ <menuitem label="&AlignDefault.label;"/>
+ <menuitem label="&AlignLeft.label;" value="left"/>
+ <menuitem label="&AlignCenter.label;" value="center"/>
+ <menuitem label="&AlignRight.label;" value="right"/>
+ </menupopup>
+ </menulist>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <hbox flex="1" style="margin-top: 0.2em">
+ <button id="RemoveFieldSet" label="&RemoveFieldSet.label;" accesskey="&RemoveFieldSet.accesskey;" oncommand="RemoveFieldSet();"/>
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdFormProps.js
@@ -0,0 +1,160 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Form Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gForm;
+var insertNew;
+var formElement;
+var formActionWarning;
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ gForm = {
+ Name: document.getElementById("FormName"),
+ Action: document.getElementById("FormAction"),
+ Method: document.getElementById("FormMethod"),
+ EncType: document.getElementById("FormEncType"),
+ Target: document.getElementById("FormTarget")
+ }
+ gDialog.MoreSection = document.getElementById("MoreSection");
+ gDialog.MoreFewerButton = document.getElementById("MoreFewerButton");
+ gDialog.RemoveForm = document.getElementById("RemoveForm")
+
+ // Get a single selected form element
+ const kTagName = "form";
+ try {
+ formElement = editor.getSelectedElement(kTagName);
+ if (!formElement)
+ formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
+ if (!formElement)
+ formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
+ } catch (e) {}
+
+ if (formElement)
+ {
+ // We found an element and don't need to insert one
+ insertNew = false;
+ formActionWarning = formElement.hasAttribute("action");
+ }
+ else
+ {
+ insertNew = true;
+ formActionWarning = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ formElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
+
+ if (!formElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ // Hide button removing existing form
+ gDialog.RemoveForm.hidden = true;
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = formElement.cloneNode(false);
+
+ InitDialog();
+
+ InitMoreFewer();
+
+ SetTextboxFocus(gForm.Name);
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ for (var attribute in gForm)
+ gForm[attribute].value = globalElement.getAttribute(attribute);
+}
+
+function RemoveForm()
+{
+ RemoveBlockContainer(formElement);
+ SaveWindowLocation();
+ window.close();
+}
+
+function ValidateData()
+{
+ for (var attribute in gForm)
+ {
+ if (gForm[attribute].value)
+ globalElement.setAttribute(attribute, gForm[attribute].value);
+ else
+ globalElement.removeAttribute(attribute);
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (formActionWarning && !gForm.Action.value)
+ {
+ AlertWithTitle(GetString("Alert"), GetString("NoFormAction"));
+ gForm.Action.focus();
+ formActionWarning = false;
+ return false;
+ }
+ // All values are valid - copy to actual element in doc or
+ // element created to insert
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ editor.cloneAttributes(formElement, globalElement);
+
+ if (insertNew)
+ InsertElementAroundSelection(formElement);
+
+ SaveWindowLocation();
+
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdFormProps.xul
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Form Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorFormProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdFormProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&Settings.label;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="FormName" value="&FormName.label;" accesskey="&FormName.accesskey;"/>
+ <textbox id="FormName"/>
+ </row>
+ <row align="center">
+ <label control="FormAction" value="&FormAction.label;" accesskey="&FormAction.accesskey;"/>
+ <textbox id="FormAction"/>
+ </row>
+ <row align="center">
+ <label control="FormMethod" value="&FormMethod.label;" accesskey="&FormMethod.accesskey;"/>
+ <hbox>
+ <menulist id="FormMethod" editable="true" autoSelectMenuitem="true">
+ <menupopup>
+ <menuitem label="GET"/>
+ <menuitem label="POST"/>
+ </menupopup>
+ </menulist>
+ </hbox>
+ </row>
+ <hbox>
+ <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
+ </hbox>
+ <rows id="MoreSection">
+ <row align="center">
+ <label control="FormEncType" value="&FormEncType.label;" accesskey="&FormEncType.accesskey;"/>
+ <menulist id="FormEncType" editable="true" autoSelectMenuitem="true">
+ <menupopup>
+ <menuitem label="application/x-www-form-urlencoded"/>
+ <menuitem label="multipart/form-data"/>
+ <menuitem label="text/plain"/>
+ </menupopup>
+ </menulist>
+ </row>
+ <row align="center">
+ <label control="FormTarget" value="&FormTarget.label;" accesskey="&FormTarget.accesskey;"/>
+ <menulist id="FormTarget" editable="true" autoSelectMenuitem="true">
+ <menupopup>
+ <menuitem label="_blank"/>
+ <menuitem label="_self"/>
+ <menuitem label="_parent"/>
+ <menuitem label="_top"/>
+ </menupopup>
+ </menulist>
+ </row>
+ </rows>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <hbox flex="1" style="margin-top: 0.2em">
+ <button id="RemoveForm" label="&RemoveForm.label;" accesskey="&RemoveForm.accesskey;" oncommand="RemoveForm();"/>
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdHLineProps.js
@@ -0,0 +1,234 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var tagName = "hr";
+var gHLineElement;
+var width;
+var height;
+var align;
+var shading;
+const gMaxHRSize = 1000; // This is hard-coded in nsHTMLHRElement::StringToAttribute()
+
+// dialog initialization code
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+ try {
+ // Get the selected horizontal line
+ gHLineElement = editor.getSelectedElement(tagName);
+ } catch (e) {}
+
+ if (!gHLineElement) {
+ // We should never be here if not editing an existing HLine
+ window.close();
+ return;
+ }
+ gDialog.heightInput = document.getElementById("height");
+ gDialog.widthInput = document.getElementById("width");
+ gDialog.leftAlign = document.getElementById("leftAlign");
+ gDialog.centerAlign = document.getElementById("centerAlign");
+ gDialog.rightAlign = document.getElementById("rightAlign");
+ gDialog.alignGroup = gDialog.rightAlign.radioGroup;
+ gDialog.shading = document.getElementById("3dShading");
+ gDialog.pixelOrPercentMenulist = document.getElementById("pixelOrPercentMenulist");
+
+ // Make a copy to use for AdvancedEdit and onSaveDefault
+ globalElement = gHLineElement.cloneNode(false);
+
+ // Initialize control values based on existing attributes
+ InitDialog()
+
+ // SET FOCUS TO FIRST CONTROL
+ SetTextboxFocus(gDialog.widthInput);
+
+ // Resize window
+ window.sizeToContent();
+
+ SetWindowLocation();
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitDialog()
+{
+ // Just to be confusing, "size" is used instead of height because it does
+ // not accept % values, only pixels
+ var height = GetHTMLOrCSSStyleValue(globalElement, "size", "height")
+ if (/px/.test(height)) {
+ height = RegExp.leftContext;
+ }
+ if(!height) {
+ height = 2; //Default value
+ }
+
+ // We will use "height" here and in UI
+ gDialog.heightInput.value = height;
+
+ // Get the width attribute of the element, stripping out "%"
+ // This sets contents of menulist (adds pixel and percent menuitems elements)
+ gDialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, gHLineElement, "width","pixelOrPercentMenulist");
+
+ var marginLeft = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-left").toLowerCase();
+ var marginRight = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-right").toLowerCase();
+ align = marginLeft + " " + marginRight;
+ gDialog.leftAlign.checked = (align == "left left" || align == "0px auto");
+ gDialog.centerAlign.checked = (align == "center center" || align == "auto auto" || align == " ");
+ gDialog.rightAlign.checked = (align == "right right" || align == "auto 0px");
+
+ if (gDialog.centerAlign.checked) {
+ gDialog.alignGroup.selectedItem = gDialog.centerAlign;
+ }
+ else if (gDialog.rightAlign.checked) {
+ gDialog.alignGroup.selectedItem = gDialog.rightAlign;
+ }
+ else {
+ gDialog.alignGroup.selectedItem = gDialog.leftAlign;
+ }
+
+ gDialog.shading.checked = !globalElement.hasAttribute("noshade");
+}
+
+function onSaveDefault()
+{
+ // "false" means set attributes on the globalElement,
+ // not the real element being edited
+ if (ValidateData()) {
+ var prefs = GetPrefs();
+ if (prefs) {
+
+ var alignInt;
+ if (align == "left") {
+ alignInt = 0;
+ } else if (align == "right") {
+ alignInt = 2;
+ } else {
+ alignInt = 1;
+ }
+ prefs.setIntPref("editor.hrule.align", alignInt);
+
+ var percent;
+ var widthInt;
+ var heightInt;
+
+ if (width)
+ {
+ if (/%/.test(width)) {
+ percent = true;
+ widthInt = Number(RegExp.leftContext);
+ } else {
+ percent = false;
+ widthInt = Number(width);
+ }
+ }
+ else
+ {
+ percent = true;
+ widthInt = Number(100);
+ }
+
+ heightInt = height ? Number(height) : 2;
+
+ prefs.setIntPref("editor.hrule.width", widthInt);
+ prefs.setBoolPref("editor.hrule.width_percent", percent);
+ prefs.setIntPref("editor.hrule.height", heightInt);
+ prefs.setBoolPref("editor.hrule.shading", shading);
+
+ // Write the prefs out NOW!
+ var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService);
+ prefService.savePrefFile(null);
+ }
+ }
+}
+
+// Get and validate data from widgets.
+// Set attributes on globalElement so they can be accessed by AdvancedEdit()
+function ValidateData()
+{
+ // Height is always pixels
+ height = ValidateNumber(gDialog.heightInput, null, 1, gMaxHRSize,
+ globalElement, "size", false);
+ if (gValidationError)
+ return false;
+
+ width = ValidateNumber(gDialog.widthInput, gDialog.pixelOrPercentMenulist, 1, gMaxPixels,
+ globalElement, "width", false);
+ if (gValidationError)
+ return false;
+
+ align = "left";
+ if (gDialog.centerAlign.selected) {
+ // Don't write out default attribute
+ align = "";
+ } else if (gDialog.rightAlign.selected) {
+ align = "right";
+ }
+ if (align)
+ globalElement.setAttribute("align", align);
+ else
+ try {
+ GetCurrentEditor().removeAttributeOrEquivalent(globalElement, "align", true);
+ } catch (e) {}
+
+ if (gDialog.shading.checked) {
+ shading = true;
+ globalElement.removeAttribute("noshade");
+ } else {
+ shading = false;
+ globalElement.setAttribute("noshade", "noshade");
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ // Copy attributes from the globalElement to the document element
+ try {
+ GetCurrentEditor().cloneAttributes(gHLineElement, globalElement);
+ } catch (e) {}
+ return true;
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdHLineProps.xul
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorHLineProperties.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <!--- Element-specific methods -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdHLineProps.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&dimensionsBox.label;"/>
+ <grid>
+ <columns><column/><column/><column /></columns>
+ <rows>
+ <row align="center">
+ <label control="width"
+ value="&widthEditField.label;"
+ accesskey="&widthEditField.accessKey;"/>
+ <textbox class="narrow" id="width" flex="1" oninput="forceInteger('width')"/>
+ <menulist id="pixelOrPercentMenulist" />
+ <!-- menupopup and menuitems added by JS -->
+ </row>
+ <row align="center">
+ <label control="height"
+ value="&heightEditField.label;"
+ accesskey="&heightEditField.accessKey;"/>
+ <textbox class="narrow" id="height" oninput="forceInteger('height')"/>
+ <label value="&pixelsPopup.value;" />
+ </row>
+ </rows>
+ </grid>
+ <checkbox id="3dShading" label="&threeDShading.label;" accesskey="&threeDShading.accessKey;"/>
+ </groupbox>
+ <groupbox><caption label="&alignmentBox.label;"/>
+ <radiogroup id="alignmentGroup" orient="horizontal">
+ <spacer class="spacer"/>
+ <radio id="leftAlign" label="&leftRadio.label;" accesskey="&leftRadio.accessKey;"/>
+ <radio id="centerAlign" label="¢erRadio.label;" accesskey="¢erRadio.accessKey;"/>
+ <radio id="rightAlign" label="&rightRadio.label;" accesskey="&rightRadio.accessKey;"/>
+ </radiogroup>
+ </groupbox>
+ <spacer class="spacer"/>
+ <hbox>
+ <button id="SaveDefault" label="&saveSettings.label;"
+ accesskey="&saveSettings.accessKey;"
+ oncommand="onSaveDefault()"
+ tooltiptext="&saveSettings.tooltip;" />
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMap.js
@@ -0,0 +1,373 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Haddix (dan6992@hotmail.com)
+ * Brian King (briano9@yahoo.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var tHide = false;
+var highCont = false;
+var imageElement = null;
+var mapName = '';
+var imageMap = null;
+var imageEl;
+var srcInputValue = null;
+var marquee = null;
+var frameDoc = null;
+var buttonArray = [];
+
+function Startup(){
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+ initDialog();
+}
+
+function initDialog(){
+ //Get image element from parent
+ imageElement = window.arguments[0];
+ if (!imageElement) //If not an image close window
+ {
+ window.close();
+ return;
+ }
+
+ //Get image map from parent
+ imageMap = window.arguments[1];
+ if (!imageMap) //If no image map close window
+ window.close();
+
+ //find parent inputs
+ var srcInput = window.opener.document.getElementById("srcInput");
+ var widthInput = window.opener.document.getElementById("widthInput");
+ var heightInput = window.opener.document.getElementById("heightInput");
+
+ //check for relative url
+ if (!((srcInput.value.indexOf("http://") != -1) || (srcInput.value.indexOf("file://") != -1))){
+ if (IsUrlAboutBlank(GetDocumentUrl())){
+ alert(GetString("SaveToUseRelativeUrl"));
+ window.close();
+ //TODO: add option to save document now
+ }
+ else{
+ var edDoc = GetDocumentUrl();
+ var imgDoc = srcInput.value;
+ imgDoc = imgDoc.split("../");
+ var len = imgDoc.length;
+ for (var i=0; i<len; i++){
+ if (edDoc.length > (String(GetCurrentEditor().document.location.protocol).length+2))
+ edDoc = edDoc.substring(0, edDoc.lastIndexOf("/"));
+ }
+ imgDoc = edDoc+"/"+imgDoc[imgDoc.length-1];
+ srcInputValue = imgDoc;
+ }
+ }
+ else{
+ srcInputValue = srcInput.value;
+ }
+
+ //Set iframe pointer
+ frameDoc = window.frames[0].document;
+
+ //Fill button array
+ buttonArray[0] = document.getElementById("pointerButton");
+ buttonArray[1] = document.getElementById("rectButton");
+ buttonArray[2] = document.getElementById("cirButton");
+ buttonArray[3] = document.getElementById("polyButton");
+
+ //Create marquee
+ var marquee = frameDoc.createElement("div");
+ marquee.setAttribute("id", "marquee");
+ frameDoc.body.appendChild(marquee);
+
+ //Create background div
+ var bgDiv = frameDoc.createElement("div");
+ if ( bgDiv ) {
+ bgDiv.setAttribute("id", "bgDiv");
+ frameDoc.body.appendChild(bgDiv);
+ }
+
+ //Place Image
+ var newImg = frameDoc.createElement("img");
+ if ( newImg ) {
+ newImg.setAttribute("src", srcInputValue);
+ if (parseInt(widthInput.value) > 0)
+ newImg.setAttribute("width", widthInput.value);
+ if (parseInt(heightInput.value) > 0)
+ newImg.setAttribute("height", heightInput.value);
+ newImg.setAttribute("id", "mainImg");
+ imageEl = frameDoc.getElementById("bgDiv").appendChild(newImg);
+ imageEl.addEventListener("error", imgError, false);
+ }
+
+ //Resize background DIV to fit image
+ fixBgDiv();
+
+ //Recreate Image Map if it exists
+ recreateMap();
+}
+
+function imgError(){
+ alert(GetString("ImapError")+" " + srcInputValue+"."+GetString("ImapCheck"));
+}
+
+function fixBgDiv(){
+ imageEl = frameDoc.getElementById("mainImg");
+ if (imageEl.offsetWidth != 0){
+ frameDoc.getElementById("bgDiv").style.width = imageEl.offsetWidth;
+ frameDoc.getElementById("bgDiv").style.height = imageEl.offsetHeight;
+ }
+ else
+ setTimeout("fixBgDiv()", 100);
+}
+
+function hideToolbar(){
+ // Check to see if toolbar is already hidden
+ if (tHide){
+ // If it is show it
+ document.getElementById("toolbar").collapsed = false;
+ // Set the menu items text back to "Hide Toolbar"
+ document.getElementById("view_hidetoolbar").setAttribute("label", GetString("HideToolbar"));
+ tHide = false
+ }
+ else{
+ // If not hide it
+ document.getElementById("toolbar").collapsed = true;
+ //Set the menu items text to "Show Toolbar"
+ document.getElementById("view_hidetoolbar").setAttribute("label", GetString("ShowToolbar"));
+ tHide = true;
+ }
+}
+
+function highContrast(){
+ if (highCont == true){
+ frameDoc.getElementById("bgDiv").style.background = "url('chrome://editor/skin/images/Map_checker.gif')";
+ frameDoc.getElementById("bgDiv").style.backgroundColor = "white";
+ imageEl.style.setProperty("opacity", "1.0", true);
+ document.getElementById("Map:Contrast").setAttribute("checked", "false");
+ document.getElementById("Map:Contrast").setAttribute("toggled", "false");
+ highCont = false;
+ }
+ else{
+ frameDoc.getElementById("bgDiv").style.background = "url('')";
+ frameDoc.getElementById("bgDiv").style.backgroundColor = "#D2D2D2";
+ imageEl.style.setProperty("opacity", ".3", true);
+ document.getElementById("Map:Contrast").setAttribute("checked", "true");
+ document.getElementById("Map:Contrast").setAttribute("toggled", "true");
+ highCont = true;
+ }
+}
+
+function recreateMap(){
+ var areaCollection = imageMap.childNodes;
+ var areaColLen = areaCollection.length;
+ for(var j=0; j<areaColLen; j++){
+ area = areaCollection[j];
+ shape = area.getAttribute("shape");
+ shape = shape.toLowerCase();
+ coords = area.getAttribute("coords");
+ href = area.getAttribute("href");
+ target = area.getAttribute("target");
+ alt = area.getAttribute("alt");
+ if (shape == "rect")
+ Rect(coords, href, target, alt, true);
+ else if (shape == "circle")
+ Circle(coords, href, target, alt, true);
+ else
+ Poly(coords, href, target, alt, true);
+ }
+}
+
+function finishMap(){
+ if (!setMapName())
+ return false;
+ if (!deleteAreas())
+ return false;
+
+ spots = frameDoc.getElementsByName("hotspot");
+ var len = spots.length;
+ if (len >= 1){
+ for(i=0; i<len; i++){
+ dump(i+"\n");
+ curSpot = spots[i];
+ if (curSpot.getAttribute("class") == "rect")
+ createRect(curSpot);
+ else if (curSpot.getAttribute("class") == "cir")
+ createCir(curSpot);
+ else
+ createPoly(curSpot);
+ }
+ //try{
+ // GetCurrentEditor().root.appendChild(imageMap);
+ //} catch (e) {}
+ //returnValue = "test";
+ //try{
+ // window.arguments[0] = "test"; //GetCurrentEditor().insertElementAtSelection(imageMap, false);
+ // dump(window.arguments[0]+"\n");
+ //} catch (e) {}
+ dump("imageMap.childNodes.length = "+imageMap.childNodes.length+"\n");
+ }
+ return true;
+}
+
+function setMapName() {
+ //try {
+ // imageMap = GetCurrentEditor().createElementWithDefaults("map");
+ //} catch (e) {}
+ //dump(imageMap+"\n");
+ //imageMap = frameDoc.createElement("map");
+
+ mapName = imageMap.getAttribute("name");
+ if (mapName == ""){
+ mapName = String(frameDoc.getElementById("mainImg").getAttribute("src"));
+ mapName = mapName.substring(mapName.lastIndexOf("/"), mapName.length);
+ mapName = mapName.substring(mapName.lastIndexOf("\\"), mapName.length);
+ mapName = mapName.substring(1, mapName.lastIndexOf("."));
+ if (mapName == ""){
+ // BUG causes substring to return nothing when
+ // parameters are 1 & 13 (i.e. string.substring(1, 13);)
+ mapName = "hack";
+ }
+ imageMap.setAttribute("name", mapName);
+}
+ return true;
+}
+
+function createRect(which){
+ var newRect;
+ //try {
+ // newRect = editor.createElementWithDefaults("area");
+ //} catch (e) {}
+ newRect = frameDoc.createElement("area");
+ newRect.setAttribute("shape", "rect");
+ coords = parseInt(which.style.left)+","+parseInt(which.style.top)+","+(parseInt(which.style.left)+parseInt(which.style.width))+","+(parseInt(which.style.top)+parseInt(which.style.height));
+ newRect.setAttribute("coords", coords);
+ if (which.getAttribute("hsHref") != ""){
+ newRect.setAttribute("href", which.getAttribute("hsHref"));
+ }
+ else{
+ newRect.setAttribute("nohref", "");
+ }
+ if (which.getAttribute("hsTarget") != ""){
+ newRect.setAttribute("target", which.getAttribute("hsTarget"));
+ }
+ if (which.getAttribute("hsAlt") != ""){
+ newRect.setAttribute("alt", which.getAttribute("hsAlt"));
+ }
+ //newRect.removeAttribute("id");
+ imageMap.appendChild(newRect);
+}
+
+function createCir(which){
+ var newCir;
+ //try {
+ // newCir = editor.createElementWithDefaults("area");
+ //} catch (e) {}
+ newCir = frameDoc.createElement("area");
+ if ( !newCir )
+ return;
+
+ newCir.setAttribute("shape", "circle");
+ radius = Math.floor(parseInt(which.style.width)/2);
+ coords = (parseInt(which.style.left)+radius)+","+(parseInt(which.style.top)+radius)+","+radius;
+ newCir.setAttribute("coords", coords);
+ if (which.getAttribute("hsHref") != "")
+ newCir.setAttribute("href", which.getAttribute("hsHref"));
+ else{
+ newCir.setAttribute("nohref", "");
+ }
+ if (which.getAttribute("hsTarget") != ""){
+ newCir.setAttribute("target", which.getAttribute("hsTarget"));
+ }
+ if (which.getAttribute("hsAlt") != ""){
+ newCir.setAttribute("alt", which.getAttribute("hsAlt"));
+ }
+ //newCir.removeAttribute("id");
+ imageMap.appendChild(newCir);
+}
+
+function createPoly(which){
+ var newPoly;
+ //try {
+ // newPoly = editor.createElementWithDefaults("area");
+ //} catch (e) {}
+ newPoly = frameDoc.createElement("area");
+ if ( !newPoly )
+ return;
+
+ newPoly.setAttribute("shape", "poly");
+ var coords = '';
+ var len = which.childNodes.length;
+ for(l=0; l<len; l++){
+ coords += (parseInt(which.style.left)+parseInt(which.childNodes[l].style.left))+","+(parseInt(which.style.top)+parseInt(which.childNodes[l].style.top))+",";
+ }
+ coords = coords.substring(0, (coords.length-1));
+ newPoly.setAttribute("coords", coords);
+ if (which.getAttribute("hsHref") != "")
+ newPoly.setAttribute("href", which.getAttribute("hsHref"));
+ else{
+ newPoly.setAttribute("nohref", "");
+ }
+ if (which.getAttribute("hsTarget") != ""){
+ newPoly.setAttribute("target", which.getAttribute("hsTarget"));
+ }
+ if (which.getAttribute("hsAlt") != ""){
+ newPoly.setAttribute("alt", which.getAttribute("hsAlt"));
+ }
+ //newPoly.removeAttribute("id");
+ imageMap.appendChild(newPoly);
+}
+
+function hotSpotProps(which){
+ var currentRect = null;
+ var currentCir = null;
+ if (which == null)
+ return;
+ hotSpotWin = window.openDialog("chrome://editor/content/EdImageMapHotSpot.xul", "_blank", "chrome,close,titlebar,modal", which);
+}
+
+function deleteAreas(){
+ dump("deleteAreas called\n");
+ area = imageMap.firstChild;
+ while (area != null){
+ dump(area+"\n");
+ imageMap.removeChild(area);
+ area = imageMap.firstChild;
+ }
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMap.xul
@@ -0,0 +1,181 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - - Brian King (briano9@yahoo.com)
+ - - Dan Haddix (dan6992@hotmail.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/EdImageMap.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorImageMap.dtd">
+
+<!-- dialog containing a control requiring initial setup -->
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ buttons="accept,cancel"
+ ondialogaccept="return finishMap();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js" />
+
+ <!-- Methods for Image Map only -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdImageMap.js" />
+ <script type="application/x-javascript" src="chrome://editor/content/EdImageMapShapes.js" />
+
+ <broadcaster id="args" value=""/>
+
+ <keyset id="dialogKeys">
+
+ <key id="deletespot" keycode="VK_DELETE" oncommand="deleteElement(currentElement)" />
+ <key id="nudgeup" keycode="VK_UP" oncommand="nudge(event, 'up')" />
+ <key id="nudgeleft" keycode="VK_LEFT" oncommand="nudge(event, 'left')" />
+ <key id="nudgedown" keycode="VK_DOWN" oncommand="nudge(event, 'down')" />
+ <key id="nudgeright" keycode="VK_RIGHT" oncommand="nudge(event, 'right')" />
+ <key id="mapclearkb" key="&clear.accesskey;" command="Map:Clear" modifiers="accel"/>
+ <key id="mapselectkb" key="&selectall.accesskey;" command="Map:SelectAll" modifiers="accel"/>
+ <key id="mapclosekb" key="&close.accesskey;" command="Map:Close" modifiers="accel"/>
+ <key id="mapcutkb" key="&cut.accesskey;" command="Map:Cut" modifiers="accel"/>
+ <key id="mapcopykb" key="©.accesskey;" command="Map:Copy" modifiers="accel"/>
+ <key id="mappastekb" key="&paste.accesskey;" command="Map:Paste" modifiers="accel"/>
+ <key id="mappropskb" key="&props.accesskey;" command="Map:Props" modifiers="accel"/>
+ <key id="maptbarkb" key="&tbar.accesskey;" command="Map:ViewToolbar" modifiers="accel"/>
+
+ </keyset>
+
+ <commandset id="commands">
+ <command id="Map:Clear" label="&clearCmd.label;" oncommand=""/>
+ <command id="Map:Close" label="&closeCmd.label;" oncommand="exitImageMap()"/>
+ <command id="Map:Copy" label="©Cmd.label;" disabled="true" oncommand="cutCopy()"/>
+ <command id="Map:Cut" label="&cutCmd.label;" disabled="true" oncommand="cutCopy(true)"/>
+ <command id="Map:Paste" label="&pasteCmd.label;" disabled="true" oncommand="paste()"/>
+ <command id="Map:Props" label="&propsCmd.label;" oncommand="hotSpotProps(currentElement[0])"/>
+ <command id="Map:ViewToolbar" label="&showhideTbarCmd.label;" oncommand="hideToolbar()"/>
+ <command id="Map:Apercent" label="&apercentCmd.label;" checked="true" oncommand="zoom('', 1)"/>
+ <command id="Map:Bpercent" label="&bpercentCmd.label;" oncommand="zoom('', 2)"/>
+ <command id="Map:Cpercent" label="&cpercentCmd.label;" oncommand="zoom('', 4)"/>
+ <command id="Map:ZoomIn" label="&zoominCmd.label;" oncommand="zoom('in')"/>
+ <command id="Map:ZoomOut" label="&zoomoutCmd.label;" disabled="true" oncommand="zoom('out')"/>
+ <command id="Map:SelectAll" label="&selectallCmd.label;" oncommand="selectAll()"/>
+ </commandset>
+
+ <!-- Interim hack to transition from nsIXULWindowCallbacks/ShowWindowWithArgs -->
+ <broadcaster id="dialog.start" ready="false"/>
+ <observes element="dialog.start" attribute="ready" onchange="EditorStartup('html')"/>
+
+<toolbox class="toolbox-top" id="ImageMapToolbox">
+<menubar persist="collapsed">
+ <!-- File menu -->
+ <menu id="mapfileMenu" label="&mapfileMenu.label;" accesskey="&mapfilemenu.accesskey;">
+ <menupopup>
+ <menuitem accesskey="&mapfileclear.accesskey;" key="mapclearkb" command="Map:Clear"/>
+ <menuitem accesskey="&mapfileclose.accesskey;" key="mapclosekb" command="Map:Close"/>
+ </menupopup>
+ </menu>
+
+ <!-- Edit menu -->
+ <menu id="mapeditMenu" label="&mapeditMenu.label;" accesskey="&mapeditmenu.accesskey;">
+ <menupopup>
+ <menuitem accesskey="&mapselectall.accesskey;" key="mapselectkb" command="Map:SelectAll"/>
+ <menuitem accesskey="&mapeditcut.accesskey;" key="mapcutkb" command="Map:Cut"/>
+ <menuitem accesskey="&mapeditcopy.accesskey;" key="mapcopykb" command="Map:Copy"/>
+ <menuitem accesskey="&mapeditpaste.accesskey;" key="mappastekb" command="Map:Paste"/>
+ <menuseparator/>
+ <menuitem accesskey="&mapeditprops.accesskey;" key="mappropskb" command="Map:Props"/>
+ </menupopup>
+ </menu>
+
+ <!-- View menu -->
+ <menu id="mapviewMenu" label="&mapviewMenu.label;" accesskey="&mapviewmenu.accesskey;">
+ <menupopup>
+ <menuitem id="view_hidetoolbar" accesskey="&mapviewtbar.accesskey;" key="maptbarkb" command="Map:ViewToolbar"/>
+ <menu id="mapscalingMenu" label="&mapviewScale.label;" accesskey="&mapviewscale.accesskey;">
+ <menupopup>
+ <menuitem accesskey="&zoomone.accesskey;" key="" command="Map:Apercent"/>
+ <menuitem accesskey="&zoomtwo.accesskey;" key="" command="Map:Bpercent"/>
+ <menuitem accesskey="&zoomthree.accesskey;" key="" command="Map:Cpercent"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+ </menu>
+
+ <spacer flex="1"/>
+</menubar>
+
+
+<toolbar id="toolbar" class="toolbar-primary" persist="collapsed">
+ <button id="cutButton" class="button-toolbar-2 top" command="Map:Cut"/>
+ <button id="copyButton" class="button-toolbar-2 top" command="Map:Copy"/>
+ <button id="pasteButton" class="button-toolbar-2 top" command="Map:Paste"/>
+ <button id="zoomInButton" class="button-toolbar-2 top" command="Map:ZoomIn"/>
+ <button id="zoomOutButton" class="button-toolbar-2 top" command="Map:ZoomOut"/>
+ <spacer flex="1"/>
+</toolbar>
+</toolbox>
+
+<hbox id="outer-box" flex="1">
+
+ <toolbar id="toolbox" orient="vertical">
+ <vbox>
+ <button id="pointerButton" class="tool" toggled="1" oncommand="changeTool(event, 'pointer');"/>
+ <button id="rectButton" class="tool" oncommand="changeTool(event, 'rect');"/>
+ <button id="cirButton" class="tool" oncommand="changeTool(event, 'cir');"/>
+ <button id="polyButton" class="tool" oncommand="changeTool(event, 'poly');"/>
+ <spacer flex="1"/>
+ </vbox>
+ </toolbar>
+
+ <!-- Content Area -->
+ <iframe id="content" src="EdImageMapPage.html" flex="1"
+ onmousedown="top.downMouse(event)"
+ onmouseup="top.upMouse(event)"
+ onmousemove="top.moveMouse(event)"
+ onclick="top.clickMouse(event)"
+ />
+
+</hbox>
+
+ <!-- from EdDialogOverlay -->
+ <!-- not sure if this is needed, but put it in just in case
+ <hbox id="AdvancedEditButton"/> -->
+
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMapHotSpot.js
@@ -0,0 +1,97 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Haddix
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// dialog initialization code
+function Startup()
+{
+ gDialog.urlInput = document.getElementById("urlInput");
+ gDialog.targetInput = document.getElementById("targetInput");
+ gDialog.altInput = document.getElementById("altInput");
+ gDialog.commonInput = document.getElementById("commonInput");
+
+ gDialog.hsHref = window.arguments[0].getAttribute("hsHref");
+ if (gDialog.hsHref != '')
+ gDialog.urlInput.value = gDialog.hsHref;
+
+ gDialog.hsAlt = window.arguments[0].getAttribute("hsAlt");
+ if (gDialog.hsAlt != '')
+ gDialog.altInput.value = gDialog.hsAlt;
+
+ gDialog.hsTarget = window.arguments[0].getAttribute("hsTarget");
+ if (gDialog.hsTarget != ''){
+ gDialog.targetInput.value = gDialog.hsTarget;
+ len = gDialog.commonInput.length;
+ for (i=0; i<len; i++){
+ if (gDialog.hsTarget == gDialog.commonInput.options[i].value)
+ gDialog.commonInput.options[i].selected = "true";
+ }
+ }
+
+ SetTextboxFocus(gDialog.urlInput);
+
+ SetWindowLocation();
+}
+
+function onAccept()
+{
+ dump(window.arguments[0].id+"\n");
+ window.arguments[0].setAttribute("hsHref", gDialog.urlInput.value);
+ window.arguments[0].setAttribute("hsAlt", gDialog.altInput.value);
+ window.arguments[0].setAttribute("hsTarget", gDialog.targetInput.value);
+
+ SaveWindowLocation();
+
+ window.close();
+}
+
+function changeTarget() {
+ gDialog.targetInput.value=gDialog.commonInput.value;
+}
+
+function chooseFile()
+{
+ // Get a local file, converted into URL format
+
+ fileName = GetLocalFileURL("html");
+ if (fileName && fileName != "") {
+ gDialog.urlInput.value = fileName;
+ }
+
+ // Put focus into the input field
+ SetTextboxFocus(gDialog.urlInput);
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMapHotSpot.xul
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Brian King
+ - Dan Haddix
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorImageMapHotSpot.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdImageMapHotSpot.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <groupbox flex="1">
+ <caption id="titleInput" label="&link.label;"/>
+
+ <grid>
+ <columns><column/><column/><column/></columns>
+ <rows>
+ <row>
+ <label control="urlInput" value="&urlFieldset.label;"/>
+
+ <textbox id="urlInput" class="MinWidth20em" value="http://"/>
+
+ <button id="Browse" oncommand="chooseFile()" label="&browseButton.label;"/>
+ </row>
+
+ <row>
+ <label control="altInput" value="&altFieldset.label;"/>
+
+ <textbox class="MinWidth20em" id="altInput"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <groupbox flex="1">
+ <caption id="targetLabel" label="&targetFieldset.label;"/>
+ <grid>
+ <columns><column/><column/><column/></columns>
+ <rows>
+ <row>
+ <label control="targetInput" value="&target.label;"/>
+ </row>
+ <row>
+ <textbox class="MinWidth20em" id="targetInput"/>
+
+ <label id="commonLabel" value="&commonFieldset.label;"/>
+
+ <menulist id="commonInput" oncommand="changeTarget()">
+ <menupopup align="center">
+ <menuitem class="middle" value="" label="&none.value;"/>
+ <menuitem class="middle" value="_self" label="&same.value;"/>
+ <menuitem class="middle" value="_top" label="&whole.value;"/>
+ <menuitem class="middle" value="_blank" label="&new.value;"/>
+ <menuitem class="middle" value="_parent" label="&parent.value;"/>
+ </menupopup>
+ </menulist>
+
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMapPage.html
@@ -0,0 +1,45 @@
+<html>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicatior Client code.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Brian King
+ - Dan Haddix
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<head>
+<title></title>
+<link rel=StyleSheet href="chrome://editor/skin/EdImageMapPage.css" type="text/css">
+</head>
+<body>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageMapShapes.js
@@ -0,0 +1,887 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Haddix (dan6992@hotmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var downTool = false;
+var dragActive = false;
+var dragObject = false;
+var startX = null;
+var startY = null;
+var endX = null;
+var endY = null;
+var downTool = false;
+var currentElement = [];
+var currentTool = "pointer";
+var currentRect = null;
+var currentCir = null;
+var currentPoly = null;
+var currentPoint = null;
+var rectCount = 1;
+var cirCount = 1;
+var polyCount = 1;
+var pointCount = 1;
+var xlock = false;
+var ylock = false;
+var resize = false;
+var currentZoom = 1;
+var clipBoard = [];
+
+function Rect(coords, href, target, alt, construct){
+ newRect = frameDoc.createElement("div");
+ newRect.setAttribute("class", "rect");
+ newRect.setAttribute("id", "rect"+rectCount++);
+ newRect.setAttribute("name", "hotspot");
+ currentRect = selectElement(frameDoc.body.appendChild(newRect));
+
+ // Add resize handles
+ // waiting for better drawing code
+ handletl = frameDoc.createElement("div");
+ handletl.setAttribute("class", "handletl");
+ handletl.setAttribute("name", "handle");
+ handletr = frameDoc.createElement("div");
+ handletr.setAttribute("class", "handletr");
+ handletr.setAttribute("name", "handle");
+ handlebl = frameDoc.createElement("div");
+ handlebl.setAttribute("class", "handlebl");
+ handlebl.setAttribute("name", "handle");
+ handlebr = frameDoc.createElement("div");
+ handlebr.setAttribute("class", "handlebr");
+ handlebr.setAttribute("name", "handle");
+ handlet = frameDoc.createElement("div");
+ handlet.setAttribute("class", "handlet");
+ handlet.setAttribute("name", "handle");
+ handlel = frameDoc.createElement("div");
+ handlel.setAttribute("class", "handlel");
+ handlel.setAttribute("name", "handle");
+ handler = frameDoc.createElement("div");
+ handler.setAttribute("class", "handler");
+ handler.setAttribute("name", "handle");
+ handleb = frameDoc.createElement("div");
+ handleb.setAttribute("class", "handleb");
+ handleb.setAttribute("name", "handle");
+ currentRect.appendChild(handletl);
+ currentRect.appendChild(handletr);
+ currentRect.appendChild(handlebl);
+ currentRect.appendChild(handlebr);
+ currentRect.appendChild(handlet);
+ currentRect.appendChild(handlel);
+ currentRect.appendChild(handler);
+ currentRect.appendChild(handleb);
+
+ if (!coords){
+ currentRect.style.left = startX+"px";
+ currentRect.style.top = startY+"px";
+ //currentRect.style.width = endX+"px";
+ //currentRect.style.height = endX+"px";
+ }
+ else{
+ var coordArray = coords.split(',');
+ currentRect.style.left = coordArray[0]+"px";
+ currentRect.style.top = coordArray[1]+"px";
+ currentRect.style.width = (parseInt(coordArray[2])-parseInt(coordArray[0]))+"px";
+ currentRect.style.height = (parseInt(coordArray[3])-parseInt(coordArray[1]))+"px";
+ if (href)
+ currentRect.setAttribute("hsHref", href);
+ if (target)
+ currentRect.setAttribute("hsTarget", target);
+ if (alt)
+ currentRect.setAttribute("hsAlt", alt);
+ }
+ if (construct)
+ currentRect = null;
+}
+
+function Circle(coords, href, target, alt, construct){
+ newCir = frameDoc.createElement("div");
+ newCir.setAttribute("class", "cir");
+ newCir.setAttribute("id", "cir"+cirCount++);
+ newCir.setAttribute("name", "hotspot");
+ currentCir = selectElement(frameDoc.body.appendChild(newCir));
+
+ // Add resize handles
+ handletl = frameDoc.createElement("div");
+ handletl.setAttribute("class", "handletl");
+ handletl.setAttribute("name", "handle");
+ handletr = frameDoc.createElement("div");
+ handletr.setAttribute("class", "handletr");
+ handletr.setAttribute("name", "handle");
+ handlebl = frameDoc.createElement("div");
+ handlebl.setAttribute("class", "handlebl");
+ handlebl.setAttribute("name", "handle");
+ handlebr = frameDoc.createElement("div");
+ handlebr.setAttribute("class", "handlebr");
+ handlebr.setAttribute("name", "handle");
+ currentCir.appendChild(handletl);
+ currentCir.appendChild(handletr);
+ currentCir.appendChild(handlebl);
+ currentCir.appendChild(handlebr);
+
+ if (!coords){
+ currentCir.style.left = startX+"px";
+ currentCir.style.top = startY+"px";
+ //currentCir.style.width = endX+"px";
+ //currentCir.style.height = endX+"px";
+ }
+ else{
+ var coordArray = coords.split(',');
+ radius = parseInt(coordArray[2]);
+ currentCir.style.left = (parseInt(coordArray[0])-radius)+"px";
+ currentCir.style.top = (parseInt(coordArray[1])-radius)+"px";
+ currentCir.style.width = (radius*2)+"px";
+ currentCir.style.height = (radius*2)+"px";
+ if (href)
+ currentCir.setAttribute("hsHref", href);
+ if (target)
+ currentCir.setAttribute("hsTarget", target);
+ if (alt)
+ currentCir.setAttribute("hsAlt", alt);
+ }
+ if (construct)
+ currentCir = null;
+}
+
+function Poly(coords, href, target, alt, construct){
+ dump('Poly Called\n');
+ newPoly = frameDoc.createElement("div");
+ newPoly.setAttribute("class", "poly");
+ newPoly.setAttribute("id", "poly"+polyCount++);
+ newPoly.setAttribute("name", "hotspot");
+ currentPoly = selectElement(frameDoc.body.appendChild(newPoly));
+ if (currentZoom > 1){
+ currentPoly.style.width = imageEl.offsetWidth+"px";
+ currentPoly.style.height = imageEl.offsetHeight+"px";
+ }
+ if (!coords){
+ addPoint(null, startX, startY, true);
+ //currentPoly.onclick = addPoint;
+ currentPoly.style.cursor = "crosshair";
+ }
+ else{
+ var coordArray = coords.split(',');
+ var len = coordArray.length;
+ for (i=0; i<len; i++){
+ addPoint(null, coordArray[i], coordArray[i+1]);
+ i++;
+ }
+ if (href)
+ currentPoly.setAttribute("hsHref", href);
+ if (target)
+ currentPoly.setAttribute("hsTarget", target);
+ if (alt)
+ currentPoly.setAttribute("hsAlt", alt);
+ polyFinish(null, construct);
+ }
+}
+
+function addPoint(event, pointX, pointY, start){
+ if (event){
+ dump('addPoint Called with event\n');
+ pointX = event.clientX+window.frames[0].pageXOffset;
+ pointY = event.clientY+window.frames[0].pageYOffset;
+ event.stopPropagation();
+ if (event.detail == 2){
+ polyFinish();
+ return;
+ }
+ }
+ else
+ dump('addPoint Called\n');
+ newPoint = frameDoc.createElement("div");
+ newPoint.setAttribute("class", "point");
+ newPoint.setAttribute("id", "point"+pointCount++);
+ newPoint.style.left = pointX+"px";
+ newPoint.style.top = pointY+"px";
+ if (start){
+ newPoint.setAttribute("class", "pointStart");
+ newPoint.style.cursor = "pointer";
+ //newPoint.onclick = polyFinish;
+ //newPoint.addEventListener("click", polyFinish, false);
+ }
+ currentPoly.appendChild(newPoint);
+}
+
+function polyFinish(event, construct){
+ dump("polyfinish called\n");
+ var len = currentPoly.childNodes.length;
+ if (len >=3){
+ var polyLeft = 1000000;
+ var polyTop = 1000000;
+ var polyWidth = 0;
+ var polyHeight = 0;
+ for(p=0; p<len; p++){
+ var curEl = currentPoly.childNodes[p];
+ curEl.setAttribute("class", "point");
+ curEl.style.cursor = "default";
+ pointLeft = parseInt(curEl.style.left);
+ pointTop = parseInt(curEl.style.top);
+ polyLeft = Math.min(polyLeft, pointLeft);
+ polyTop = Math.min(polyTop, pointTop);
+ dump(polyLeft+"\n");
+ }
+ for(p=0; p<len; p++){
+ var curEl = currentPoly.childNodes[p];
+ curEl.style.left = (parseInt(curEl.style.left)-polyLeft)+"px";
+ curEl.style.top = (parseInt(curEl.style.top)-polyTop)+"px";
+ }
+ for(p=0; p<len; p++){
+ var curEl = currentPoly.childNodes[p];
+ polyWidth = Math.max(polyWidth, (parseInt(curEl.style.left)+3));
+ polyHeight = Math.max(polyHeight, (parseInt(curEl.style.top)+3));
+ }
+ if (parseInt(currentPoly.style.left) >= 0){
+ polyLeft += parseInt(currentPoly.style.left);
+ polyTop += parseInt(currentPoly.style.top);
+ }
+ currentPoly.style.left = polyLeft+"px";
+ currentPoly.style.top = polyTop+"px";
+ currentPoly.style.width = polyWidth+"px";
+ currentPoly.style.height = polyHeight+"px";
+ //currentPoly.childNodes[0].onclick = null;
+ //currentPoly.onclick = null;
+ currentPoly.style.cursor = "auto";
+ //currentPoly.childNodes[0].removeEventListener("click", polyFinish, false);
+ //currentPoly.removeEventListener("click", addPoint, true);
+ if (!construct)
+ hotSpotProps(currentPoly);
+ }
+ else
+ deleteElement(currentPoly);
+ if (event)
+ event.stopPropagation();
+
+ currentPoly = null;
+}
+
+function deleteElement(el){
+ if (el){
+ if (el.length){
+ var len = currentElement.length;
+ for(i=0; i<len; i++)
+ frameDoc.body.removeChild(currentElement[i]);
+ }
+ else
+ frameDoc.body.removeChild(el);
+ }
+}
+
+function selectAll(){
+ objList = frameDoc.getElementsByName("hotspot");
+ listLen = objList.length;
+ var objCount = 0;
+ for(a=0; a<listLen; a++){
+ selectElement(objList[a], objCount);
+ objCount++;
+ }
+}
+
+function selectElement(el, add){
+ if (add){
+ if (currentElement[0].getAttribute("class") != "poly"){
+ len = currentElement[0].childNodes.length;
+ for(i=0; i<len; i++)
+ currentElement[0].childNodes[i].style.visibility = "hidden";
+ }
+ currentElement.push(el);
+ document.getElementById("Map:Cut").setAttribute("disabled", "false");
+ document.getElementById("Map:Copy").setAttribute("disabled", "false");
+ return currentElement[currentElement.length-1];
+ }
+ else{
+ if (currentElement[0]){
+ if (currentElement[0].getAttribute("class") != "poly"){
+ len = currentElement[0].childNodes.length;
+ for(i=0; i<len; i++)
+ currentElement[0].childNodes[i].style.visibility = "hidden";
+ }
+ }
+ currentElement = null;
+ currentElement = [];
+ currentElement[0] = el;
+ if (el != null){
+ if (currentElement[0].getAttribute("class") != "poly"){
+ len = currentElement[0].childNodes.length;
+ for(i=0; i<len; i++)
+ currentElement[0].childNodes[i].style.visibility = "visible";
+ }
+ document.getElementById("Map:Cut").setAttribute("disabled", "false");
+ document.getElementById("Map:Copy").setAttribute("disabled", "false");
+ return currentElement[0];
+ }
+ else{
+ document.getElementById("Map:Cut").setAttribute("disabled", "true");
+ document.getElementById("Map:Copy").setAttribute("disabled", "true");
+ }
+ }
+}
+
+function deSelectElement(el){
+ var len = currentElement.length;
+ var j=0;
+ for(i=0; i<len; i++){
+ dump(j+"\n");
+ currentElement[j] = currentElement[i];
+ if (currentElement[i] != el)
+ j++;
+ }
+ currentElement.pop();
+ if (currentElement.length == 1){
+ selectElement(currentElement[0]);
+ }
+ if (currentElement.length >= 1){
+ document.getElementById("Map:Cut").setAttribute("disabled", "false");
+ document.getElementById("Map:Copy").setAttribute("disabled", "false");
+ }
+ else{
+ document.getElementById("Map:Cut").setAttribute("disabled", "true");
+ document.getElementById("Map:Copy").setAttribute("disabled", "true");
+ }
+}
+
+function marqueeSelect(){
+ marTop = parseInt(marquee.style.top);
+ marLeft = parseInt(marquee.style.left);
+ marRight = parseInt(marquee.style.width)+marLeft;
+ marBottom = parseInt(marquee.style.height)+marTop;
+ marquee.style.visibility = "hidden";
+ marquee.style.top = "-5px";
+ marquee.style.left = "-5px";
+ marquee.style.width = "1px";
+ marquee.style.height = "1px";
+ marquee = null;
+ objList = frameDoc.getElementsByName("hotspot");
+ listLen = objList.length;
+ var objCount = 0;
+ for(a=0; a<listLen; a++){
+ objTop = parseInt(objList[a].style.top);
+ objLeft = parseInt(objList[a].style.left);
+ objRight = parseInt(objList[a].style.width)+objLeft;
+ objBottom = parseInt(objList[a].style.height)+objTop;
+ if ((objTop >= marTop) && (objLeft >= marLeft) && (objBottom <= marBottom) && (objRight <= marRight)){
+ //objList[i].style.borderColor = "#ffff00";
+ selectElement(objList[a], objCount);
+ objCount++;
+ }
+ }
+}
+
+function upMouse(event){
+ if (currentTool != "poly"){
+ if (marquee){
+ marqueeSelect();
+ }
+ if (currentRect){
+ if (!resize)
+ hotSpotProps(currentRect);
+ else
+ resize = false;
+ }
+ else if (currentCir){
+ if (!resize)
+ hotSpotProps(currentCir);
+ else
+ resize = false;
+ }
+ else if (currentPoint)
+ polyFinish(null, true);
+
+ currentRect = null;
+ currentCir = null;
+ currentPoint=null;
+ downTool = false;
+ dragActive = false;
+ dragObject = false;
+ xlock = false;
+ ylock = false;
+ }
+}
+
+function moveMouse(event){
+ if (downTool){
+ endX = event.clientX+window.frames[0].pageXOffset;
+ endY = event.clientY+window.frames[0].pageYOffset;
+
+ if (dragActive){
+ if (currentElement.length > 0){
+ if (currentCir){
+ radiusWidth = Math.abs((endX-startX));
+ radiusHeight = Math.abs((endY-startY));
+ circleRadius = Math.max(radiusWidth, radiusHeight);
+ currentCir.style.top = Math.max(startY-circleRadius, 0)+"px";
+ currentCir.style.left = Math.max(startX-circleRadius, 0)+"px";
+ currentCir.style.width = (circleRadius*2)+"px";
+ currentCir.style.height = (circleRadius*2)+"px";
+ }
+ else if (currentRect || marquee){
+ var rectObject = (currentRect)? currentRect : marquee;
+ if (!xlock){
+ if (endX > startX){
+ rectWidth = endX-startX;
+ rectObject.style.left = Math.max(startX, 0 )+"px";
+ rectObject.style.width = rectWidth+"px";
+ }
+ else{
+ rectWidth = startX-endX;
+ rectObject.style.left = Math.max(endX, 0)+"px";
+ rectObject.style.width = rectWidth+"px";
+ }
+ }
+ if (!ylock){
+ if (endY > startY){
+ rectHeight = endY-startY;
+ rectObject.style.top = startY+"px";
+ rectObject.style.height = rectHeight+"px";
+ }
+ else{
+ rectHeight = startY-endY;
+ rectObject.style.top = endY+"px";
+ rectObject.style.height = rectHeight+"px";
+ }
+ }
+ }
+ }
+ }
+ else{
+ if (currentTool == "rect"){
+ if ((((endX-startX) > 1) || ((endX-startX) < -1)) && (((endY-startY) > 1) || ((endY-startY) < -1))){
+ Rect();
+ dragActive = true;
+ }
+ }
+ if (currentTool == "cir"){
+ if ((((endX-startX) > 1) || ((endX-startX) < -1)) && (((endY-startY) > 1) || ((endY-startY) < -1))){
+ Circle();
+ dragActive = true;
+ }
+ }
+ if (currentTool == "pointer"){
+ if (dragObject){
+ var len = currentElement.length;
+ var maxX = false;
+ var maxY = false;
+ for(i=0; i<len; i++){
+ newX = Math.max(0, (endX-currentElement[i].startX));
+ newY = Math.max(0, (endY-currentElement[i].startY));
+ if (newX == 0)
+ maxX = true;
+ if (newY == 0)
+ maxY = true;
+ }
+ for(i=0; i<len; i++){
+ newX = Math.max(0, (endX-currentElement[i].startX));
+ newY = Math.max(0, (endY-currentElement[i].startY));
+ if ((newX > 0) && (maxX != true))
+ currentElement[i].style.left = newX+"px";
+ if ((newY >0) && (maxY != true))
+ currentElement[i].style.top = newY+"px";
+ }
+ }
+ else if (currentPoint){
+ endX = endX-parseInt(currentPoint.parentNode.style.left);
+ endY = endY-parseInt(currentPoint.parentNode.style.top);
+ newX = Math.max((0-parseInt(currentPoint.parentNode.style.left)), (endX-currentPoint.startX));
+ newY = Math.max((0-parseInt(currentPoint.parentNode.style.top)), (endY-currentPoint.startY));
+ currentPoint.style.left = newX+"px";
+ currentPoint.style.top = newY+"px";
+ }
+ else{
+ marquee = frameDoc.getElementById("marquee");
+ marquee.style.visibility = "visible";
+ dragActive = true;
+ }
+ }
+ }
+ }
+}
+
+
+function downMouse(event){
+ dump(event.target.parentNode.id+"\n");
+ if (event.button == 0){
+ if (currentTool != "poly"){
+ startX = event.clientX+window.frames[0].pageXOffset;
+ startY = event.clientY+window.frames[0].pageYOffset;
+ downTool = true;
+ if (currentTool == "pointer"){
+ if (event.target.getAttribute("name") == "hotspot"){
+ var el = event.target;
+ var isSelected = false;
+
+ if (event.target.getAttribute("cir") == "true")
+ el = event.target.parentNode;
+
+ if (event.shiftKey){
+ var len = currentElement.length;
+ var deselect = false;
+ for(i=0; i<len; i++){
+ if (currentElement[i] == el){
+ deSelectElement(el);
+ return;
+ }
+ }
+ selectElement(el, true);
+ isSelected = true;
+ }
+ else{
+ var len = currentElement.length;
+ for(i=0; i<len; i++){
+ if (currentElement[i] == el)
+ isSelected = true;
+ }
+ }
+
+ if (isSelected){
+ var len = currentElement.length;
+ for(i=0; i<len; i++){
+ currentElement[i].startX = parseInt(event.clientX+window.frames[0].pageXOffset)-parseInt(currentElement[i].style.left);
+ currentElement[i].startY = parseInt(event.clientY+window.frames[0].pageYOffset)-parseInt(currentElement[i].style.top);
+ }
+ }
+ else{
+ curObj = selectElement(el);
+ curObj.startX = parseInt(event.clientX+window.frames[0].pageXOffset)-parseInt(curObj.style.left);
+ curObj.startY = parseInt(event.clientY+window.frames[0].pageYOffset)-parseInt(curObj.style.top);
+ }
+ dragObject = true;
+ }
+ else if (event.target.getAttribute("name") == "handle"){
+ dump("down on a handle\n");
+ resize = true;
+ el = event.target;
+ curObj = selectElement(el.parentNode);
+ if (curObj.className == "rect"){
+ currentRect = curObj;
+ switch (el.className){
+ case "handletl":
+ startX = parseInt(curObj.style.left)+parseInt(curObj.style.width);
+ startY = parseInt(curObj.style.top)+parseInt(curObj.style.height);
+ break;
+ case "handletr":
+ startX = parseInt(curObj.style.left);
+ startY = parseInt(curObj.style.top)+parseInt(curObj.style.height);
+ break;
+ case "handlebl":
+ startX = parseInt(curObj.style.left)+parseInt(curObj.style.width);
+ startY = parseInt(curObj.style.top);
+ break;
+ case "handlebr":
+ startX = parseInt(curObj.style.left);
+ startY = parseInt(curObj.style.top);
+ break;
+ case "handlet":
+ xlock = true;
+ startY = parseInt(curObj.style.top)+parseInt(curObj.style.height);
+ break;
+ case "handleb":
+ xlock = true;
+ startY = parseInt(curObj.style.top);
+ break;
+ case "handlel":
+ ylock = true;
+ startX = parseInt(curObj.style.left)+parseInt(curObj.style.width);
+ break;
+ case "handler":
+ ylock = true;
+ startX = parseInt(curObj.style.left);
+ break;
+ default:
+ return;
+ }
+ }
+ else{
+ currentCir = curObj;
+ startX = parseInt(curObj.style.left)+(parseInt(curObj.style.width)/2);
+ startY = parseInt(curObj.style.top)+(parseInt(curObj.style.height)/2);
+ }
+ }
+ else if (event.target.getAttribute("class") == "point"){
+ dump("down on a point\n");
+ selectElement(event.target.parentNode);
+ currentPoint = event.target;
+ currentPoint.startX = parseInt(event.clientX+window.frames[0].pageXOffset)-(parseInt(currentPoint.style.left)+parseInt(currentPoint.parentNode.style.left));
+ currentPoint.startY = parseInt(event.clientY+window.frames[0].pageYOffset)-(parseInt(currentPoint.style.top)+parseInt(currentPoint.parentNode.style.top));
+ currentPoly = currentPoint.parentNode;
+ }
+ else{
+ dump(event.target+"\n");
+ selectElement(null);
+ }
+ }
+ }
+ }
+}
+
+function clickMouse(event){
+ if (event.button == 0){
+ dump("body clicked\n");
+ //alert(frameDoc.+'\n');
+ startX = event.clientX+window.frames[0].pageXOffset;
+ startY = event.clientY+window.frames[0].pageYOffset;
+ if (currentTool == "poly"){
+ if (event.target != currentPoly){
+ if (currentPoly != null){
+ if (event.target == currentPoly.childNodes[0]){
+ polyFinish();
+ }
+ else if (event.detail == 2){
+ polyFinish();
+ }
+ }
+ else{
+ Poly();
+ }
+ }
+ else{
+ addPoint(event);
+ }
+ }
+ }
+}
+
+function changeTool(event, what){
+ if (!currentPoly){
+ for(i=0; i<4; i++){
+ buttonArray[i].setAttribute("toggled", 0);
+ if (event.target == buttonArray[i]){
+ buttonArray[i].setAttribute("toggled", 1);
+ }
+ }
+ currentTool = what;
+ if (currentTool != "pointer"){
+ frameDoc.getElementById("bgDiv").style.cursor = "crosshair";
+ frameDoc.body.style.cursor = "crosshair";
+ }
+ else{
+ frameDoc.getElementById("bgDiv").style.cursor = "default";
+ frameDoc.body.style.cursor = "default";
+ }
+
+ dump(what+" selected\n");
+ }
+ else {
+ for(i=0; i<4; i++){
+ if (event.target == buttonArray[i]){
+ buttonArray[i].setAttribute("toggled", 0);
+ }
+ }
+ }
+}
+
+function zoom(direction, ratio){
+ dump('zoom called; ratio='+ratio+'\n');
+ if (direction == "in")
+ ratio = currentZoom*2;
+ else if (direction == "out")
+ ratio = currentZoom/2;
+
+ if (ratio > 4 || ratio < 1 || ratio == currentZoom)
+ return;
+
+ if (ratio == 1){
+ document.getElementById('Map:ZoomIn').setAttribute('disabled', 'false');
+ document.getElementById('Map:ZoomOut').setAttribute('disabled', 'true');
+ document.getElementById('Map:Apercent').setAttribute('checked', 'true');
+ document.getElementById('Map:Bpercent').setAttribute('checked', 'false');
+ document.getElementById('Map:Cpercent').setAttribute('checked', 'false');
+ }
+ else if (ratio == 4){
+ document.getElementById('Map:ZoomIn').setAttribute('disabled', 'true');
+ document.getElementById('Map:ZoomOut').setAttribute('disabled', 'false');
+ document.getElementById('Map:Apercent').setAttribute('checked', 'false');
+ document.getElementById('Map:Bpercent').setAttribute('checked', 'false');
+ document.getElementById('Map:Cpercent').setAttribute('checked', 'true');
+ }
+ else {
+ document.getElementById('Map:ZoomIn').setAttribute('disabled', 'false');
+ document.getElementById('Map:ZoomOut').setAttribute('disabled', 'false');
+ document.getElementById('Map:Apercent').setAttribute('checked', 'false');
+ document.getElementById('Map:Bpercent').setAttribute('checked', 'true');
+ document.getElementById('Map:Cpercent').setAttribute('checked', 'false');
+ }
+
+ objList = frameDoc.getElementsByName("hotspot");
+ len = objList.length;
+ for(i=0; i<len; i++){
+ if (ratio > currentZoom){
+ objList[i].style.width = (parseInt(objList[i].style.width)*(ratio/currentZoom))+"px";
+ objList[i].style.height = (parseInt(objList[i].style.height)*(ratio/currentZoom))+"px";
+ objList[i].style.top = (parseInt(objList[i].style.top)*(ratio/currentZoom))+"px";
+ objList[i].style.left = (parseInt(objList[i].style.left)*(ratio/currentZoom))+"px";
+ }
+ else{
+ objList[i].style.width = (parseInt(objList[i].style.width)/(currentZoom/ratio))+"px";
+ objList[i].style.height = (parseInt(objList[i].style.height)/(currentZoom/ratio))+"px";
+ objList[i].style.top = (parseInt(objList[i].style.top)/(currentZoom/ratio))+"px";
+ objList[i].style.left = (parseInt(objList[i].style.left)/(currentZoom/ratio))+"px";
+ }
+ if (objList[i].getAttribute("class") == "poly"){
+ pointList = objList[i].childNodes;
+ plen = pointList.length;
+ dump('i='+i+'\n');
+ for(j=0; j<plen; j++){
+ dump('i='+i+'\n');
+ if (ratio > currentZoom){
+ pointList[j].style.top = (parseInt(pointList[j].style.top)*(ratio/currentZoom))+"px";
+ pointList[j].style.left = (parseInt(pointList[j].style.left)*(ratio/currentZoom))+"px";
+ }
+ else{
+ pointList[j].style.top = (parseInt(pointList[j].style.top)/(currentZoom/ratio))+"px";
+ pointList[j].style.left = (parseInt(pointList[j].style.left)/(currentZoom/ratio))+"px";
+ }
+ }
+ currentPoly = objList[i];
+ polyFinish(null, true);
+ currentPoly = null;
+ }
+ dump('i='+i+'\n');
+ }
+
+ imgEl = frameDoc.getElementById("mainImg");
+ bgDiv = frameDoc.getElementById("bgDiv");
+ dump(imgEl.getAttribute("width")+'\n');
+ if (ratio > currentZoom){
+ imgEl.setAttribute("width", (parseInt(imgEl.offsetWidth)*(ratio/currentZoom)));
+ imgEl.setAttribute("height", (parseInt(imgEl.offsetHeight)*(ratio/currentZoom)));
+ bgDiv.style.width = imgEl.offsetWidth;
+ bgDiv.style.height = imgEl.offsetHeight;
+ }
+ else{
+ imgEl.setAttribute("width", (parseInt(imgEl.offsetWidth)/(currentZoom/ratio)));
+ imgEl.setAttribute("height", (parseInt(imgEl.offsetHeight)/(currentZoom/ratio)));
+ bgDiv.style.width = imgEl.offsetWidth;
+ bgDiv.style.height = imgEl.offsetHeight;
+ }
+ currentZoom = ratio;
+}
+
+function cutCopy(cut){
+ len = currentElement.length;
+ if (len >= 1){
+ clipBoard = [];
+ for (i=0; i<len; i++){
+ el = currentElement[i];
+ if (el.className == 'rect'){
+ coords = parseInt(el.style.left)+","+parseInt(el.style.top)+","+(parseInt(el.style.left)+parseInt(el.style.width))+","+(parseInt(el.style.top)+parseInt(el.style.height));
+ href = el.getAttribute('hsHref');
+ target = el.getAttribute('hsTarget');
+ alt = el.getAttribute('hsAlt');
+ clipBoard[i] = 'Rect(\"'+coords+'\", \"'+href+'\", \"'+target+'\", \"'+alt+'\", true)';
+ }
+ else if (el.className == 'cir'){
+ radius = Math.floor(parseInt(el.style.width)/2);
+ coords = (parseInt(el.style.left)+radius)+","+(parseInt(el.style.top)+radius)+","+radius;
+ href = el.getAttribute('href');
+ target = el.getAttribute('hsTarget');
+ alt = el.getAttribute('hsAlt');
+ clipBoard[i] = 'Circle(\"'+coords+'\", \"'+href+'\", \"'+target+'\", \"'+alt+'\", true)';
+ }
+ else{
+ var coords = '';
+ var pointlen = el.childNodes.length;
+ for(j=0; j<pointlen; j++){
+ coords += (parseInt(el.style.left)+parseInt(el.childNodes[j].style.left))+","+(parseInt(el.style.top)+parseInt(el.childNodes[j].style.top))+",";
+ }
+ coords = coords.substring(0, (coords.length-1));
+ href = el.getAttribute('href');
+ target = el.getAttribute('hsTarget');
+ alt = el.getAttribute('hsAlt');
+ clipBoard[i] = 'Poly(\"'+coords+'\", \"'+href+'\", \"'+target+'\", \"'+alt+'\", true)';
+ }
+ if (cut){
+ deleteElement(el);
+ }
+ }
+ document.getElementById('Map:Paste').setAttribute('disabled', 'false');
+ }
+}
+
+function paste(){
+ len = clipBoard.length;
+ func = '';
+ for (i=0; i<len; i++){
+ func += clipBoard[i]+'\;';
+ }
+ eval(func);
+}
+
+ function nudge(event, dir){
+ /*prevent scrolling
+ event.stopPropagation();
+ event.preventDefault();*/
+
+ len = currentElement.length;
+ amount = 1;
+ if (event.shiftKey)
+ amount = 5;
+
+
+ boundRectTop = 1000000;
+ boundRectLeft = 1000000;
+ for (i=0; i<len; i++){
+ curTop = parseInt(currentElement[i].style.top);
+ curLeft = parseInt(currentElement[i].style.left);
+ if (curTop < boundRectTop)
+ boundRectTop = curTop;
+ if (curLeft < boundRectLeft)
+ boundRectLeft = curLeft;
+ }
+
+ for (i=0; i<len; i++){
+ if (dir == "up"){
+ curTop = parseInt(currentElement[i].style.top);
+ if (boundRectTop >= amount)
+ currentElement[i].style.top = (curTop-amount) + "px";
+ else
+ currentElement[i].style.top = (curTop-boundRectTop) + "px";
+ }
+ else if (dir == "left"){
+ curLeft = parseInt(currentElement[i].style.left);
+ if (boundRectLeft >= amount)
+ currentElement[i].style.left = (curLeft-amount) + "px";
+ else
+ currentElement[i].style.left = (curLeft-boundRectLeft) + "px";
+ }
+ else if (dir == "down"){
+ curTop = parseInt(currentElement[i].style.top);
+ currentElement[i].style.top = (curTop+amount) + "px";
+ }
+ else if (dir == "right"){
+ curLeft = parseInt(currentElement[i].style.left);
+ currentElement[i].style.left = (curLeft+amount) + "px";
+ }
+ }
+}
+
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageOverlay.js
@@ -0,0 +1,653 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Editor Image Properties Overlay.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pete Collins
+ * Brian King
+ * Ben Goodger
+ * Neil Rashbrook <neil@parkwaycc.co.uk> (Separated from EdImageProps.js)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Note: We encourage non-empty alt text for images inserted into a page.
+ When there's no alt text, we always write 'alt=""' as the attribute, since "alt" is a required attribute.
+ We allow users to not have alt text by checking a "Don't use alterate text" radio button,
+ and we don't accept spaces as valid alt text. A space used to be required to avoid the error message
+ if user didn't enter alt text, but is unnecessary now that we no longer annoy the user
+ with the error dialog if alt="" is present on an img element.
+ We trim all spaces at the beginning and end of user's alt text
+*/
+
+var gInsertNewImage = true;
+var gInsertNewIMap = true;
+var gDoAltTextError = false;
+var gConstrainOn = false;
+// Note used in current version, but these are set correctly
+// and could be used to reset width and height used for constrain ratio
+var gConstrainWidth = 0;
+var gConstrainHeight = 0;
+var imageElement;
+var gImageMap = 0;
+var gCanRemoveImageMap = false;
+var gRemoveImageMap = false;
+var gImageMapDisabled = false;
+var gActualWidth = "";
+var gActualHeight = "";
+var gOriginalSrc = "";
+var gHaveDocumentUrl = false;
+var gTimerID;
+var gValidateTab;
+
+// These must correspond to values in EditorDialog.css for each theme
+// (unfortunately, setting "style" attribute here doesn't work!)
+var gPreviewImageWidth = 80;
+var gPreviewImageHeight = 50;
+
+// dialog initialization code
+
+function ImageStartup()
+{
+ gDialog.tabBox = document.getElementById( "TabBox" );
+ gDialog.tabLocation = document.getElementById( "imageLocationTab" );
+ gDialog.tabDimensions = document.getElementById( "imageDimensionsTab" );
+ gDialog.tabBorder = document.getElementById( "imageBorderTab" );
+ gDialog.srcInput = document.getElementById( "srcInput" );
+ gDialog.titleInput = document.getElementById( "titleInput" );
+ gDialog.altTextInput = document.getElementById( "altTextInput" );
+ gDialog.altTextRadioGroup = document.getElementById( "altTextRadioGroup" );
+ gDialog.altTextRadio = document.getElementById( "altTextRadio" );
+ gDialog.noAltTextRadio = document.getElementById( "noAltTextRadio" );
+ gDialog.customSizeRadio = document.getElementById( "customSizeRadio" );
+ gDialog.actualSizeRadio = document.getElementById( "actualSizeRadio" );
+ gDialog.constrainCheckbox = document.getElementById( "constrainCheckbox" );
+ gDialog.widthInput = document.getElementById( "widthInput" );
+ gDialog.heightInput = document.getElementById( "heightInput" );
+ gDialog.widthUnitsMenulist = document.getElementById( "widthUnitsMenulist" );
+ gDialog.heightUnitsMenulist = document.getElementById( "heightUnitsMenulist" );
+ gDialog.imagelrInput = document.getElementById( "imageleftrightInput" );
+ gDialog.imagetbInput = document.getElementById( "imagetopbottomInput" );
+ gDialog.border = document.getElementById( "border" );
+ gDialog.alignTypeSelect = document.getElementById( "alignTypeSelect" );
+ gDialog.ImageHolder = document.getElementById( "preview-image-holder" );
+ gDialog.PreviewWidth = document.getElementById( "PreviewWidth" );
+ gDialog.PreviewHeight = document.getElementById( "PreviewHeight" );
+ gDialog.PreviewSize = document.getElementById( "PreviewSize" );
+ gDialog.PreviewImage = null;
+ gDialog.OkButton = document.documentElement.getButton("accept");
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitImage()
+{
+ // Set the controls to the image's attributes
+ gDialog.srcInput.value = globalElement.getAttribute("src");
+
+ // Set "Relativize" checkbox according to current URL state
+ SetRelativeCheckbox();
+
+ // Force loading of image from its source and show preview image
+ LoadPreviewImage();
+
+ if (globalElement.hasAttribute("title"))
+ gDialog.titleInput.value = globalElement.getAttribute("title");
+
+ var hasAltText = globalElement.hasAttribute("alt");
+ var altText;
+ if (hasAltText)
+ {
+ altText = globalElement.getAttribute("alt");
+ gDialog.altTextInput.value = altText;
+ }
+
+ // Initialize altText widgets during dialog startup
+ // or if user enterred altText in Advanced Edit dialog
+ // (this preserves "Don't use alt text" radio button state)
+ if (!gDialog.altTextRadioGroup.selectedItem || altText)
+ {
+ if (gInsertNewImage || !hasAltText || (hasAltText && gDialog.altTextInput.value))
+ {
+ SetAltTextDisabled(false);
+ gDialog.altTextRadioGroup.selectedItem = gDialog.altTextRadio;
+ }
+ else
+ {
+ SetAltTextDisabled(true);
+ gDialog.altTextRadioGroup.selectedItem = gDialog.noAltTextRadio;
+ }
+ }
+
+ // setup the height and width widgets
+ var width = InitPixelOrPercentMenulist(globalElement,
+ gInsertNewImage ? null : imageElement,
+ "width", "widthUnitsMenulist", gPixel);
+ var height = InitPixelOrPercentMenulist(globalElement,
+ gInsertNewImage ? null : imageElement,
+ "height", "heightUnitsMenulist", gPixel);
+
+ // Set actual radio button if both set values are the same as actual
+ SetSizeWidgets(width, height);
+
+ gDialog.widthInput.value = gConstrainWidth = width ? width : (gActualWidth ? gActualWidth : "");
+ gDialog.heightInput.value = gConstrainHeight = height ? height : (gActualHeight ? gActualHeight : "");
+
+ // set spacing editfields
+ gDialog.imagelrInput.value = globalElement.getAttribute("hspace");
+ gDialog.imagetbInput.value = globalElement.getAttribute("vspace");
+
+ // dialog.border.value = globalElement.getAttribute("border");
+ var bv = GetHTMLOrCSSStyleValue(globalElement, "border", "border-top-width");
+ if (/px/.test(bv))
+ {
+ // Strip out the px
+ bv = RegExp.leftContext;
+ }
+ else if (bv == "thin")
+ {
+ bv = "1";
+ }
+ else if (bv == "medium")
+ {
+ bv = "3";
+ }
+ else if (bv == "thick")
+ {
+ bv = "5";
+ }
+ gDialog.border.value = bv;
+
+ // Get alignment setting
+ var align = globalElement.getAttribute("align");
+ if (align)
+ align = align.toLowerCase();
+
+ var imgClass;
+ var textID;
+
+ switch ( align )
+ {
+ case "top":
+ case "middle":
+ case "right":
+ case "left":
+ gDialog.alignTypeSelect.value = align;
+ break;
+ default: // Default or "bottom"
+ gDialog.alignTypeSelect.value = "bottom";
+ }
+
+ // Get image map for image
+ gImageMap = GetImageMap();
+
+ doOverallEnabling();
+ doDimensionEnabling();
+}
+
+function SetSizeWidgets(width, height)
+{
+ if (!(width || height) || (gActualWidth && gActualHeight && width == gActualWidth && height == gActualHeight))
+ gDialog.actualSizeRadio.radioGroup.selectedItem = gDialog.actualSizeRadio;
+
+ if (!gDialog.actualSizeRadio.selected)
+ {
+ gDialog.actualSizeRadio.radioGroup.selectedItem = gDialog.customSizeRadio;
+
+ // Decide if user's sizes are in the same ratio as actual sizes
+ if (gActualWidth && gActualHeight)
+ {
+ if (gActualWidth > gActualHeight)
+ gDialog.constrainCheckbox.checked = (Math.round(gActualHeight * width / gActualWidth) == height);
+ else
+ gDialog.constrainCheckbox.checked = (Math.round(gActualWidth * height / gActualHeight) == width);
+ }
+ }
+}
+
+// Disable alt text input when "Don't use alt" radio is checked
+function SetAltTextDisabled(disable)
+{
+ gDialog.altTextInput.disabled = disable;
+}
+
+function GetImageMap()
+{
+ var usemap = globalElement.getAttribute("usemap");
+ if (usemap)
+ {
+ gCanRemoveImageMap = true;
+ var mapname = usemap.substring(1, usemap.length);
+ var mapCollection;
+ try {
+ mapCollection = GetCurrentEditor().document.getElementsByName(mapname);
+ } catch (e) {}
+ if (mapCollection && mapCollection[0] != null)
+ {
+ gInsertNewIMap = false;
+ return mapCollection[0];
+ }
+ }
+ else
+ {
+ gCanRemoveImageMap = false;
+ }
+
+ gInsertNewIMap = true;
+ return null;
+}
+
+function chooseFile()
+{
+ if (gTimerID)
+ clearTimeout(gTimerID);
+ // Get a local file, converted into URL format
+ var fileName = GetLocalFileURL("img");
+ if (fileName)
+ {
+ // Always try to relativize local file URLs
+ if (gHaveDocumentUrl)
+ fileName = MakeRelativeUrl(fileName);
+
+ gDialog.srcInput.value = fileName;
+
+ SetRelativeCheckbox();
+ doOverallEnabling();
+ }
+ LoadPreviewImage();
+
+ // Put focus into the input field
+ SetTextboxFocus(gDialog.srcInput);
+}
+
+function PreviewImageLoaded()
+{
+ if (gDialog.PreviewImage)
+ {
+ // Image loading has completed -- we can get actual width
+ gActualWidth = gDialog.PreviewImage.naturalWidth;
+ gActualHeight = gDialog.PreviewImage.naturalHeight;
+
+ if (gActualWidth && gActualHeight)
+ {
+ // Use actual size or scale to fit preview if either dimension is too large
+ var width = gActualWidth;
+ var height = gActualHeight;
+ if (gActualWidth > gPreviewImageWidth)
+ {
+ width = gPreviewImageWidth;
+ height = gActualHeight * (gPreviewImageWidth / gActualWidth);
+ }
+ if (height > gPreviewImageHeight)
+ {
+ height = gPreviewImageHeight;
+ width = gActualWidth * (gPreviewImageHeight / gActualHeight);
+ }
+ gDialog.PreviewImage.width = width;
+ gDialog.PreviewImage.height = height;
+
+ gDialog.PreviewWidth.setAttribute("value", gActualWidth);
+ gDialog.PreviewHeight.setAttribute("value", gActualHeight);
+
+ gDialog.PreviewSize.collapsed = false;
+ gDialog.ImageHolder.collapsed = false;
+
+ SetSizeWidgets(gDialog.widthInput.value, gDialog.heightInput.value);
+ }
+
+ if (gDialog.actualSizeRadio.selected)
+ SetActualSize();
+ }
+}
+
+function LoadPreviewImage()
+{
+ gDialog.PreviewSize.collapsed = true;
+ // XXXbz workaround for bug 265416 / bug 266284
+ gDialog.ImageHolder.collapsed = true;
+
+ var imageSrc = TrimString(gDialog.srcInput.value);
+ if (!imageSrc)
+ return;
+
+ try {
+ // Remove the image URL from image cache so it loads fresh
+ // (if we don't do this, loads after the first will always use image cache
+ // and we won't see image edit changes or be able to get actual width and height)
+
+ var IOService = GetIOService();
+ if (IOService)
+ {
+ // We must have an absolute URL to preview it or remove it from the cache
+ imageSrc = MakeAbsoluteUrl(imageSrc);
+
+ if (GetScheme(imageSrc))
+ {
+ var uri = IOService.newURI(imageSrc, null, null);
+ if (uri)
+ {
+ var imgCacheService = Components.classes["@mozilla.org/image/cache;1"].getService();
+ var imgCache = imgCacheService.QueryInterface(Components.interfaces.imgICache);
+
+ // This returns error if image wasn't in the cache; ignore that
+ imgCache.removeEntry(uri);
+ }
+ }
+ }
+ } catch(e) {}
+
+ if (gDialog.PreviewImage)
+ removeEventListener("load", PreviewImageLoaded, true);
+
+ if (gDialog.ImageHolder.firstChild)
+ gDialog.ImageHolder.removeChild(gDialog.ImageHolder.firstChild);
+
+ gDialog.PreviewImage = document.createElementNS("http://www.w3.org/1999/xhtml", "html:img");
+ if (gDialog.PreviewImage)
+ {
+ // set the src before appending to the document -- see bug 198435 for why
+ // this is needed.
+ // XXXbz that bug is long-since fixed. Is this still needed?
+ gDialog.PreviewImage.addEventListener("load", PreviewImageLoaded, true);
+ gDialog.PreviewImage.src = imageSrc;
+ gDialog.ImageHolder.appendChild(gDialog.PreviewImage);
+ }
+}
+
+function SetActualSize()
+{
+ gDialog.widthInput.value = gActualWidth ? gActualWidth : "";
+ gDialog.widthUnitsMenulist.selectedIndex = 0;
+ gDialog.heightInput.value = gActualHeight ? gActualHeight : "";
+ gDialog.heightUnitsMenulist.selectedIndex = 0;
+ doDimensionEnabling();
+}
+
+function ChangeImageSrc()
+{
+ if (gTimerID)
+ clearTimeout(gTimerID);
+
+ gTimerID = setTimeout("LoadPreviewImage()", 800);
+
+ SetRelativeCheckbox();
+ doOverallEnabling();
+}
+
+function doDimensionEnabling()
+{
+ // Enabled only if "Custom" is selected
+ var enable = (gDialog.customSizeRadio.selected);
+
+ // BUG 74145: After input field is disabled,
+ // setting it enabled causes blinking caret to appear
+ // even though focus isn't set to it.
+ SetElementEnabledById( "heightInput", enable );
+ SetElementEnabledById( "heightLabel", enable );
+ SetElementEnabledById( "heightUnitsMenulist", enable );
+
+ SetElementEnabledById( "widthInput", enable );
+ SetElementEnabledById( "widthLabel", enable);
+ SetElementEnabledById( "widthUnitsMenulist", enable );
+
+ var constrainEnable = enable
+ && ( gDialog.widthUnitsMenulist.selectedIndex == 0 )
+ && ( gDialog.heightUnitsMenulist.selectedIndex == 0 );
+
+ SetElementEnabledById( "constrainCheckbox", constrainEnable );
+}
+
+function doOverallEnabling()
+{
+ var enabled = TrimString(gDialog.srcInput.value) != "";
+
+ SetElementEnabled(gDialog.OkButton, enabled);
+ SetElementEnabledById("AdvancedEditButton1", enabled);
+ SetElementEnabledById("imagemapLabel", enabled);
+
+ //TODO: Restore when Image Map editor is finished
+ //SetElementEnabledById("editImageMap", enabled);
+ SetElementEnabledById("removeImageMap", gCanRemoveImageMap);
+}
+
+function ToggleConstrain()
+{
+ // If just turned on, save the current width and height as basis for constrain ratio
+ // Thus clicking on/off lets user say "Use these values as aspect ration"
+ if (gDialog.constrainCheckbox.checked && !gDialog.constrainCheckbox.disabled
+ && (gDialog.widthUnitsMenulist.selectedIndex == 0)
+ && (gDialog.heightUnitsMenulist.selectedIndex == 0))
+ {
+ gConstrainWidth = Number(TrimString(gDialog.widthInput.value));
+ gConstrainHeight = Number(TrimString(gDialog.heightInput.value));
+ }
+}
+
+function constrainProportions( srcID, destID )
+{
+ var srcElement = document.getElementById(srcID);
+ if (!srcElement)
+ return;
+
+ var destElement = document.getElementById(destID);
+ if (!destElement)
+ return;
+
+ // always force an integer (whether we are constraining or not)
+ forceInteger(srcID);
+
+ if (!gActualWidth || !gActualHeight ||
+ !(gDialog.constrainCheckbox.checked && !gDialog.constrainCheckbox.disabled))
+ return;
+
+ // double-check that neither width nor height is in percent mode; bail if so!
+ if ( (gDialog.widthUnitsMenulist.selectedIndex != 0)
+ || (gDialog.heightUnitsMenulist.selectedIndex != 0) )
+ return;
+
+ // This always uses the actual width and height ratios
+ // which is kind of funky if you change one number without the constrain
+ // and then turn constrain on and change a number
+ // I prefer the old strategy (below) but I can see some merit to this solution
+ if (srcID == "widthInput")
+ destElement.value = Math.round( srcElement.value * gActualHeight / gActualWidth );
+ else
+ destElement.value = Math.round( srcElement.value * gActualWidth / gActualHeight );
+
+/*
+ // With this strategy, the width and height ratio
+ // can be reset to whatever the user entered.
+ if (srcID == "widthInput")
+ destElement.value = Math.round( srcElement.value * gConstrainHeight / gConstrainWidth );
+ else
+ destElement.value = Math.round( srcElement.value * gConstrainWidth / gConstrainHeight );
+*/
+}
+
+function editImageMap()
+{
+ // Create an imagemap for image map editor
+ if (gInsertNewIMap)
+ {
+ try {
+ gImageMap = GetCurrentEditor().createElementWithDefaults("map");
+ } catch (e) {}
+ }
+
+ // Note: We no longer pass in a copy of the global ImageMap. ImageMap editor should create a copy and manage onOk and onCancel behavior
+ window.openDialog("chrome://editor/content/EdImageMap.xul", "_blank", "chrome,close,titlebar,modal", globalElement, gImageMap);
+}
+
+function removeImageMap()
+{
+ gRemoveImageMap = true;
+ gCanRemoveImageMap = false;
+ SetElementEnabledById("removeImageMap", false);
+}
+
+function SwitchToValidatePanel()
+{
+ if (gDialog.tabBox && gValidateTab && gDialog.tabBox.selectedTab != gValidateTab)
+ gDialog.tabBox.selectedTab = gValidateTab;
+}
+
+// Get data from widgets, validate, and set for the global element
+// accessible to AdvancedEdit() [in EdDialogCommon.js]
+function ValidateImage()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ return false;
+
+ gValidateTab = gDialog.tabLocation;
+ if (!gDialog.srcInput.value)
+ {
+ AlertWithTitle(null, GetString("MissingImageError"));
+ SwitchToValidatePanel();
+ gDialog.srcInput.focus();
+ return false;
+ }
+
+ // We must convert to "file:///" or "http://" format else image doesn't load!
+ var src = TrimString(gDialog.srcInput.value);
+ var checkbox = document.getElementById("MakeRelativeCheckbox");
+ try
+ {
+ if (checkbox && !checkbox.checked)
+ {
+ var URIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
+ .getService(Components.interfaces.nsIURIFixup);
+ src = URIFixup.createFixupURI(src, Components.interfaces.nsIURIFixup.FIXUP_FLAG_NONE).spec;
+ }
+ } catch (e) { }
+
+ globalElement.setAttribute("src", src);
+
+ var title = TrimString(gDialog.titleInput.value);
+ if (title)
+ globalElement.setAttribute("title", title);
+ else
+ globalElement.removeAttribute("title");
+
+ // Force user to enter Alt text only if "Alternate text" radio is checked
+ // Don't allow just spaces in alt text
+ var alt = "";
+ var useAlt = gDialog.altTextRadioGroup.selectedItem == gDialog.altTextRadio;
+ if (useAlt)
+ alt = TrimString(gDialog.altTextInput.value);
+
+ if (gDoAltTextError && useAlt && !alt)
+ {
+ AlertWithTitle(null, GetString("NoAltText"));
+ SwitchToValidatePanel();
+ gDialog.altTextInput.focus();
+ return false;
+ }
+ globalElement.setAttribute("alt", alt);
+
+ var width = "";
+ var height = "";
+
+ gValidateTab = gDialog.tabDimensions;
+ if (!gDialog.actualSizeRadio.selected)
+ {
+ // Get user values for width and height
+ width = ValidateNumber(gDialog.widthInput, gDialog.widthUnitsMenulist, 1, gMaxPixels,
+ globalElement, "width", false, true);
+ if (gValidationError)
+ return false;
+
+ height = ValidateNumber(gDialog.heightInput, gDialog.heightUnitsMenulist, 1, gMaxPixels,
+ globalElement, "height", false, true);
+ if (gValidationError)
+ return false;
+ }
+
+ // We always set the width and height attributes, even if same as actual.
+ // This speeds up layout of pages since sizes are known before image is loaded
+ if (!width)
+ width = gActualWidth;
+ if (!height)
+ height = gActualHeight;
+
+ // Remove existing width and height only if source changed
+ // and we couldn't obtain actual dimensions
+ var srcChanged = (src != gOriginalSrc);
+ if (width)
+ editor.setAttributeOrEquivalent(globalElement, "width", width, true);
+ else if (srcChanged)
+ editor.removeAttributeOrEquivalent(globalElement, "width", true);
+
+ if (height)
+ editor.setAttributeOrEquivalent(globalElement, "height", height, true);
+ else if (srcChanged)
+ editor.removeAttributeOrEquivalent(globalElement, "height", true);
+
+ // spacing attributes
+ gValidateTab = gDialog.tabBorder;
+ ValidateNumber(gDialog.imagelrInput, null, 0, gMaxPixels,
+ globalElement, "hspace", false, true, true);
+ if (gValidationError)
+ return false;
+
+ ValidateNumber(gDialog.imagetbInput, null, 0, gMaxPixels,
+ globalElement, "vspace", false, true);
+ if (gValidationError)
+ return false;
+
+ // note this is deprecated and should be converted to stylesheets
+ ValidateNumber(gDialog.border, null, 0, gMaxPixels,
+ globalElement, "border", false, true);
+ if (gValidationError)
+ return false;
+
+ // Default or setting "bottom" means don't set the attribute
+ // Note that the attributes "left" and "right" are opposite
+ // of what we use in the UI, which describes where the TEXT wraps,
+ // not the image location (which is what the HTML describes)
+ switch ( gDialog.alignTypeSelect.value )
+ {
+ case "top":
+ case "middle":
+ case "right":
+ case "left":
+ editor.setAttributeOrEquivalent( globalElement, "align",
+ gDialog.alignTypeSelect.value , true);
+ break;
+ default:
+ try {
+ editor.removeAttributeOrEquivalent(globalElement, "align", true);
+ } catch (e) {}
+ }
+
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageOverlay.xul
@@ -0,0 +1,296 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Image Properties Overlay.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Pete Collins
+ - Brian King
+ - Neil Rashbrook <neil@parkwaycc.co.uk> (Separated from EdImageProps.xul)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/EditorImageProperties.dtd">
+
+<overlay id="EdImageOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="chrome://editor/content/EdImageOverlay.js"/>
+
+ <tab id="imageInputTab" label="&imageInputTab.label;"/>
+ <tab id="imageLocationTab" label="&imageLocationTab.label;"/>
+ <tab id="imageDimensionsTab" label="&imageDimensionsTab.label;"/>
+ <tab id="imageAppearanceTab" label="&imageAppearanceTab.label;"/>
+ <tab id="imageLinkTab" label="&imageLinkTab.label;"/>
+
+ <vbox id="imageLocation">
+ <spacer class="spacer"/>
+ <label control = "srcInput"
+ value = "&locationEditField.label;"
+ accesskey="&locationEditField.accessKey;"
+ tooltiptext="&locationEditField.tooltip;"
+ />
+ <textbox id="srcInput" oninput="ChangeImageSrc();" tabindex="1" class="uri-element"/>
+ <hbox id="MakeRelativeHbox">
+ <checkbox
+ id = "MakeRelativeCheckbox"
+ for = "srcInput"
+ tabindex="2"/>
+ <!-- mail compose will insert custom item here defined in mailComposeEditorOverlay.xul -->
+ <spacer flex="1"/>
+ <!-- from EdDialogOverlay.xul -->
+ <button id="ChooseFile" tabindex="3"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <radiogroup id="altTextRadioGroup" flex="1">
+ <grid>
+ <columns><column/><column flex="1"/></columns>
+ <rows>
+ <row align="center">
+ <label
+ style = "margin-left: 26px"
+ control = "titleInput"
+ accesskey = "&title.accessKey;"
+ value ="&title.label;"
+ tooltiptext="&title.tooltip;"
+ for = "titleInput"/>
+ <textbox flex="1"
+ id = "titleInput"
+ class = "MinWidth20em"
+ tooltiptext="&title.tooltip;"
+ tabindex="4"/>
+ </row>
+ <row align="center">
+ <radio id = "altTextRadio"
+ label = "&altText.label;"
+ accesskey = "&altText.accessKey;"
+ tooltiptext="&altTextEditField.tooltip;"
+ oncommand = "SetAltTextDisabled(false);"
+ tabindex="5"/>
+ <textbox flex="1"
+ id = "altTextInput"
+ class = "MinWidth20em"
+ tooltiptext="&altTextEditField.tooltip;"
+ oninput = "SetAltTextDisabled(false);"
+ tabindex="6"/>
+ </row>
+ </rows>
+ </grid>
+
+ <radio id = "noAltTextRadio"
+ label = "&noAltText.label;"
+ accesskey = "&noAltText.accessKey;"
+ oncommand = "SetAltTextDisabled(true);"/>
+ </radiogroup>
+ </vbox>
+
+ <groupbox id="imagePreview" orient="horizontal" flex="1">
+ <caption label="&previewBox.label;"/>
+ <hbox id="preview-image-box" align="center">
+ <spacer flex="1"/>
+ <description id="preview-image-holder"/>
+ <spacer flex="1"/>
+ </hbox>
+ <vbox id="PreviewSize" collapsed="true">
+ <spacer flex="1"/>
+ <label value="&actualSize.label;"/>
+ <hbox>
+ <label value="&widthEditField.label;"/>
+ <spacer flex="1"/>
+ <label id="PreviewWidth"/>
+ </hbox>
+ <hbox>
+ <label value="&heightEditField.label;"/>
+ <spacer flex="1"/>
+ <label id="PreviewHeight"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox>
+ </groupbox>
+
+ <vbox id="imageDimensions" align="start">
+ <spacer class="spacer"/>
+ <hbox>
+ <radiogroup id="imgSizeGroup">
+ <radio
+ id = "actualSizeRadio"
+ label = "&actualSizeRadio.label;"
+ accesskey = "&actualSizeRadio.accessKey;"
+ tooltiptext="&actualSizeRadio.tooltip;"
+ oncommand = "SetActualSize()"/>
+ <radio
+ id = "customSizeRadio"
+ label = "&customSizeRadio.label;"
+ accesskey = "&customSizeRadio.accessKey;"
+ tooltiptext="&customSizeRadio.tooltip;"
+ oncommand = "doDimensionEnabling();" />
+ </radiogroup>
+ <spacer flex="1"/>
+ <vbox>
+ <spacer flex="1"/>
+ <checkbox id="constrainCheckbox" label="&constrainCheckbox.label;"
+ accesskey="&constrainCheckbox.accessKey;"
+ oncommand="ToggleConstrain()"
+ tooltiptext="&constrainCheckbox.tooltip;"/>
+ </vbox>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <grid class="indent">
+ <columns><column/><column/><column flex="1"/></columns>
+ <rows>
+ <row align="center">
+ <label id = "widthLabel"
+ control = "widthInput"
+ accesskey = "&widthEditField.accessKey;"
+ value = "&widthEditField.label;" />
+ <textbox
+ id = "widthInput"
+ class = "narrow"
+ oninput = "constrainProportions(this.id, 'heightInput')"/>
+ <menulist id = "widthUnitsMenulist"
+ oncommand = "doDimensionEnabling();" />
+ <!-- contents are appended by JS -->
+ </row>
+ <row align="center">
+ <label id = "heightLabel"
+ control = "heightInput"
+ accesskey = "&heightEditField.accessKey;"
+ value = "&heightEditField.label;" />
+ <textbox
+ id = "heightInput"
+ class = "narrow"
+ oninput = "constrainProportions(this.id, 'widthInput')"/>
+ <menulist id = "heightUnitsMenulist"
+ oncommand = "doDimensionEnabling();" />
+ <!-- contents are appended by JS -->
+ </row>
+ </rows>
+ </grid>
+ <spacer flex="1"/>
+ </vbox>
+
+ <hbox id="imageAppearance">
+ <groupbox>
+ <caption id="spacingLabel" label="&spacingBox.label;"/>
+ <grid>
+ <columns><column/><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label
+ class = "align-right"
+ id = "leftrightLabel"
+ control = "imageleftrightInput"
+ accesskey = "&leftRightEditField.accessKey;"
+ value = "&leftRightEditField.label;"/>
+ <textbox
+ class = "narrow"
+ id = "imageleftrightInput"
+ oninput = "forceInteger(this.id)"/>
+ <label
+ id = "leftrighttypeLabel"
+ value = "&pixelsPopup.value;" />
+ </row>
+ <spacer class="spacer"/>
+ <row align="center">
+ <label
+ class = "align-right"
+ id = "topbottomLabel"
+ control = "imagetopbottomInput"
+ accesskey = "&topBottomEditField.accessKey;"
+ value = "&topBottomEditField.label;"/>
+ <textbox
+ class = "narrow"
+ id = "imagetopbottomInput"
+ oninput = "forceInteger(this.id)"/>
+ <label
+ id = "topbottomtypeLabel"
+ value = "&pixelsPopup.value;" />
+ </row>
+ <spacer class="spacer"/>
+ <row align="center">
+ <label class = "align-right"
+ id = "borderLabel"
+ control = "border"
+ accesskey = "&borderEditField.accessKey;"
+ value = "&borderEditField.label;"/>
+ <textbox
+ class = "narrow"
+ id = "border"
+ oninput = "forceInteger(this.id)"/>
+ <label
+ id = "bordertypeLabel"
+ value = "&pixelsPopup.value;" />
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <vbox>
+ <groupbox align="start">
+ <caption id="alignLabel" label="&alignment.label;"/>
+ <menulist id="alignTypeSelect" class="align-menu">
+ <menupopup>
+ <menuitem class="align-menu" value="top" label="&topPopup.value;"/>
+ <menuitem class="align-menu" value="middle" label="¢erPopup.value;"/>
+ <menuitem class="align-menu" value="bottom" label="&bottomPopup.value;"/>
+ <!-- HTML attribute value is opposite of the button label on purpose -->
+ <menuitem class="align-menu" value="right" label="&wrapLeftPopup.value;"/>
+ <menuitem class="align-menu" value="left" label="&wrapRightPopup.value;"/>
+ </menupopup>
+ </menulist>
+ </groupbox>
+
+ <groupbox>
+ <caption id="imagemapLabel" label="&imagemapBox.label;"/>
+ <hbox equalsize="always">
+
+<!-- Hide Image Map Editor. Not ready for prime time yet
+ <button
+ id = "editImageMap"
+ oncommand = "editImageMap()"
+ tooltiptext="&editImageMapButton.tooltip;"
+ label = "&editImageMapButton.label;"
+ flex = "1"/>
+-->
+ <button
+ id = "removeImageMap"
+ oncommand = "removeImageMap()"
+ accesskey = "&removeImageMapButton.accessKey;"
+ label = "&removeImageMapButton.label;"
+ flex = "1"/>
+ <spacer flex="1"/><!-- remove when we restore Image Map Editor -->
+ </hbox>
+ </groupbox>
+ </vbox>
+ </hbox>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageProps.js
@@ -0,0 +1,320 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pete Collins
+ * Brian King
+ * Ben Goodger
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gAnchorElement = null;
+var gOriginalHref = "";
+var gHNodeArray = {};
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ ImageStartup();
+ gDialog.hrefInput = document.getElementById("hrefInput");
+ gDialog.makeRelativeLink = document.getElementById("MakeRelativeLink");
+ gDialog.showLinkBorder = document.getElementById("showLinkBorder");
+ gDialog.linkTab = document.getElementById("imageLinkTab");
+
+ // Get a single selected image element
+ var tagName = "img";
+ if ("arguments" in window && window.arguments[0])
+ {
+ imageElement = window.arguments[0];
+ // We've been called from form field propertes, so we can't insert a link
+ gDialog.linkTab.parentNode.removeChild(gDialog.linkTab);
+ gDialog.linkTab = null;
+ }
+ else
+ {
+ // First check for <input type="image">
+ try {
+ imageElement = editor.getSelectedElement("input");
+
+ if (!imageElement || imageElement.getAttribute("type") != "image") {
+ // Get a single selected image element
+ imageElement = editor.getSelectedElement(tagName);
+ if (imageElement)
+ gAnchorElement = editor.getElementOrParentByTagName("href", imageElement);
+ }
+ } catch (e) {}
+
+ }
+
+ if (imageElement)
+ {
+ // We found an element and don't need to insert one
+ if (imageElement.hasAttribute("src"))
+ {
+ gInsertNewImage = false;
+ gActualWidth = imageElement.naturalWidth;
+ gActualHeight = imageElement.naturalHeight;
+ }
+ }
+ else
+ {
+ gInsertNewImage = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ imageElement = editor.createElementWithDefaults(tagName);
+ } catch(e) {}
+
+ if (!imageElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ try {
+ gAnchorElement = editor.getSelectedElement("href");
+ } catch (e) {}
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = imageElement.cloneNode(false);
+
+ // We only need to test for this once per dialog load
+ gHaveDocumentUrl = GetDocumentBaseUrl();
+
+ InitDialog();
+ if (gAnchorElement)
+ gOriginalHref = gAnchorElement.getAttribute("href");
+ gDialog.hrefInput.value = gOriginalHref;
+
+ FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
+ ChangeLinkLocation();
+
+ // Save initial source URL
+ gOriginalSrc = gDialog.srcInput.value;
+
+ // By default turn constrain on, but both width and height must be in pixels
+ gDialog.constrainCheckbox.checked =
+ gDialog.widthUnitsMenulist.selectedIndex == 0 &&
+ gDialog.heightUnitsMenulist.selectedIndex == 0;
+
+ // Start in "Link" tab if 2nd arguement is true
+ if (gDialog.linkTab && "arguments" in window && window.arguments[1])
+ {
+ document.getElementById("TabBox").selectedTab = gDialog.linkTab;
+ SetTextboxFocus(gDialog.hrefInput);
+ }
+ else
+ SetTextboxFocus(gDialog.srcInput);
+
+ SetWindowLocation();
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitDialog()
+{
+ InitImage();
+ var border = TrimString(gDialog.border.value);
+ gDialog.showLinkBorder.checked = border != "" && border > 0;
+}
+
+function ChangeLinkLocation()
+{
+ SetRelativeCheckbox(gDialog.makeRelativeLink);
+ gDialog.showLinkBorder.disabled = !TrimString(gDialog.hrefInput.value);
+}
+
+function ToggleShowLinkBorder()
+{
+ if (gDialog.showLinkBorder.checked)
+ {
+ var border = TrimString(gDialog.border.value);
+ if (!border || border == "0")
+ gDialog.border.value = "2";
+ }
+ else
+ {
+ gDialog.border.value = "0";
+ }
+}
+
+// Get data from widgets, validate, and set for the global element
+// accessible to AdvancedEdit() [in EdDialogCommon.js]
+function ValidateData()
+{
+ return ValidateImage();
+}
+
+function onAccept()
+{
+ // Use this now (default = false) so Advanced Edit button dialog doesn't trigger error message
+ gDoAltTextError = true;
+
+ if (ValidateData())
+ {
+ if ("arguments" in window && window.arguments[0])
+ {
+ SaveWindowLocation();
+ return true;
+ }
+
+ var editor = GetCurrentEditor();
+
+ editor.beginTransaction();
+
+ try
+ {
+ if (gRemoveImageMap)
+ {
+ globalElement.removeAttribute("usemap");
+ if (gImageMap)
+ {
+ editor.deleteNode(gImageMap);
+ gInsertNewIMap = true;
+ gImageMap = null;
+ }
+ }
+ else if (gImageMap)
+ {
+ // un-comment to see that inserting image maps does not work!
+ /*
+ gImageMap = editor.createElementWithDefaults("map");
+ gImageMap.setAttribute("name", "testing");
+ var testArea = editor.createElementWithDefaults("area");
+ testArea.setAttribute("shape", "circle");
+ testArea.setAttribute("coords", "86,102,52");
+ testArea.setAttribute("href", "test");
+ gImageMap.appendChild(testArea);
+ */
+
+ // Assign to map if there is one
+ var mapName = gImageMap.getAttribute("name");
+ if (mapName != "")
+ {
+ globalElement.setAttribute("usemap", ("#"+mapName));
+ if (globalElement.getAttribute("border") == "")
+ globalElement.setAttribute("border", 0);
+ }
+ }
+
+ // Create or remove the link as appropriate
+ var href = gDialog.hrefInput.value;
+ if (href != gOriginalHref)
+ {
+ if (href && !gInsertNewImage)
+ EditorSetTextProperty("a", "href", href);
+ else
+ EditorRemoveTextProperty("href", "");
+ }
+
+ // If inside a link, always write the 'border' attribute
+ if (href)
+ {
+ if (gDialog.showLinkBorder.checked)
+ {
+ // Use default = 2 if border attribute is empty
+ if (!globalElement.hasAttribute("border"))
+ globalElement.setAttribute("border", "2");
+ }
+ else
+ globalElement.setAttribute("border", "0");
+ }
+
+ if (gInsertNewImage)
+ {
+ if (href) {
+ var linkElement = editor.createElementWithDefaults("a");
+ linkElement.setAttribute("href", href);
+ linkElement.appendChild(imageElement);
+ editor.insertElementAtSelection(linkElement, true);
+ }
+ else
+ // 'true' means delete the selection before inserting
+ editor.insertElementAtSelection(imageElement, true);
+ }
+
+ // Check to see if the link was to a heading
+ // Do this last because it moves the caret (BAD!)
+ if (href in gHNodeArray)
+ {
+ var anchorNode = editor.createElementWithDefaults("a");
+ if (anchorNode)
+ {
+ anchorNode.name = href.substr(1);
+ // Remember to use editor method so it is undoable!
+ editor.insertNode(anchorNode, gHNodeArray[href], 0, false);
+ }
+ }
+ // All values are valid - copy to actual element in doc or
+ // element we just inserted
+ editor.cloneAttributes(imageElement, globalElement);
+
+ // If document is empty, the map element won't insert,
+ // so always insert the image first
+ if (gImageMap && gInsertNewIMap)
+ {
+ // Insert the ImageMap element at beginning of document
+ var body = editor.rootElement;
+ editor.setShouldTxnSetSelection(false);
+ editor.insertNode(gImageMap, body, 0);
+ editor.setShouldTxnSetSelection(true);
+ }
+ }
+ catch (e)
+ {
+ dump(e);
+ }
+
+ editor.endTransaction();
+
+ SaveWindowLocation();
+ return true;
+ }
+
+ gDoAltTextError = false;
+
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdImageProps.xul
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Pete Collins
+ - Brian King
+ - Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdImageOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorImageProperties.dtd">
+
+
+<!-- dialog containing a control requiring initial setup -->
+<dialog id="imageDlg" title="&windowTitle.label;"
+ xmlns ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdImageProps.js"/>
+ <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <tabbox id="TabBox">
+ <tabs flex="1">
+ <tab id="imageLocationTab"/>
+ <tab id="imageDimensionsTab"/>
+ <tab id="imageAppearanceTab"/>
+ <tab id="imageLinkTab"/>
+ </tabs>
+ <tabpanels>
+ <!-- panels overlayed from EdImageOverlay.xul -->
+ <vbox id="imageLocation"/>
+ <vbox id="imageDimensions"/>
+ <hbox id="imageAppearance"/>
+ <vbox>
+ <spacer class="spacer"/>
+ <vbox id="LinkLocationBox"/>
+ <spacer class="spacer"/>
+ <checkbox id="showLinkBorder"
+ label="&showImageLinkBorder.label;"
+ accesskey="&showImageLinkBorder.accessKey;"
+ oncommand="ToggleShowLinkBorder();"/>
+ </vbox>
+ </tabpanels>
+ </tabbox>
+
+ <hbox align="end">
+ <groupbox id="imagePreview"/>
+
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+ </hbox>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInputImage.js
@@ -0,0 +1,211 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Input Tag Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ gDialog = {
+ inputName: document.getElementById( "InputName" ),
+ inputDisabled: document.getElementById( "InputDisabled" ),
+ inputTabIndex: document.getElementById( "InputTabIndex" )
+ };
+
+ ImageStartup();
+
+ // Get a single selected input element
+ var tagName = "input";
+ try {
+ imageElement = editor.getSelectedElement(tagName);
+ } catch (e) {}
+
+ if (imageElement)
+ {
+ // We found an element and don't need to insert one
+ gInsertNewImage = false;
+ }
+ else
+ {
+ gInsertNewImage = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ imageElement = editor.createElementWithDefaults(tagName);
+ } catch(e) {}
+
+ if (!imageElement )
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ var imgElement;
+ try {
+ imgElement = editor.getSelectedElement("img");
+ } catch(e) {}
+
+ if (imgElement)
+ {
+ // We found an image element, convert it to an input type="image"
+ var attributes = ["src", "alt", "width", "height", "hspace", "vspace", "border", "align", "usemap", "ismap"];
+ for (i in attributes)
+ imageElement.setAttribute(attributes[i], imgElement.getAttribute(attributes[i]));
+ }
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = imageElement.cloneNode(false);
+
+ // We only need to test for this once per dialog load
+ gHaveDocumentUrl = GetDocumentBaseUrl();
+
+ InitDialog();
+
+ // Save initial source URL
+ gOriginalSrc = gDialog.srcInput.value;
+
+ // By default turn constrain on, but both width and height must be in pixels
+ gDialog.constrainCheckbox.checked =
+ gDialog.widthUnitsMenulist.selectedIndex == 0 &&
+ gDialog.heightUnitsMenulist.selectedIndex == 0;
+
+ SetTextboxFocus(gDialog.inputName);
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ InitImage();
+ gDialog.inputName.value = globalElement.getAttribute("name");
+ gDialog.inputDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
+ gDialog.inputTabIndex.value = globalElement.getAttribute("tabindex");
+}
+
+function ValidateData()
+{
+ if (!ValidateImage())
+ return false;
+ if (gDialog.inputName.value)
+ globalElement.setAttribute("name", gDialog.inputName.value);
+ else
+ globalElement.removeAttribute("name");
+ if (gDialog.inputTabIndex.value)
+ globalElement.setAttribute("tabindex", gDialog.inputTabIndex.value);
+ else
+ globalElement.removeAttribute("tabindex");
+ if (gDialog.inputDisabled.checked)
+ globalElement.setAttribute("disabled", "");
+ else
+ globalElement.removeAttribute("disabled");
+ globalElement.setAttribute("type", "image");
+ return true;
+}
+
+function onAccept()
+{
+ // Show alt text error only once
+ // (we don't initialize doAltTextError=true
+ // so Advanced edit button dialog doesn't trigger that error message)
+ // Use this now (default = false) so Advanced Edit button dialog doesn't trigger error message
+ gDoAltTextError = true;
+
+ if (ValidateData())
+ {
+
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ if (gRemoveImageMap)
+ {
+ globalElement.removeAttribute("usemap");
+ if (gImageMap)
+ {
+ editor.deleteNode(gImageMap);
+ gInsertNewIMap = true;
+ gImageMap = null;
+ }
+ }
+ else if (gImageMap)
+ {
+ // Assign to map if there is one
+ var mapName = gImageMap.getAttribute("name");
+ if (mapName != "")
+ {
+ globalElement.setAttribute("usemap", ("#"+mapName));
+ if (globalElement.getAttribute("border") == "")
+ globalElement.setAttribute("border", 0);
+ }
+ }
+
+ if (gInsertNewImage)
+ {
+ // 'true' means delete the selection before inserting
+ // in case were are converting an image to an input type="image"
+ editor.insertElementAtSelection(imageElement, true);
+ }
+ editor.cloneAttributes(imageElement, globalElement);
+
+ // If document is empty, the map element won't insert,
+ // so always insert the image element first
+ if (gImageMap && gInsertNewIMap)
+ {
+ // Insert the ImageMap element at beginning of document
+ var body = editor.rootElement;
+ editor.setShouldTxnSetSelection(false);
+ editor.insertNode(gImageMap, body, 0);
+ editor.setShouldTxnSetSelection(true);
+ }
+ } catch (e) {}
+
+ editor.endTransaction();
+
+ SaveWindowLocation();
+
+ return true;
+ }
+ return false;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInputImage.xul
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Input Tag Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdImageOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInputProperties.dtd">
+<dialog title="&windowTitleImage.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInputImage.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <tabbox id="TabBox">
+ <tabs flex="1">
+ <tab id="imageInputTab"/>
+ <tab id="imageLocationTab"/>
+ <tab id="imageDimensionsTab"/>
+ <tab id="imageAppearanceTab"/>
+ </tabs>
+ <tabpanels>
+ <groupbox><caption label="&InputSettings.label;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label value="&InputName.label;"/>
+ <textbox id="InputName"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="InputDisabled" label="&InputDisabled.label;"/>
+ </row>
+ <row align="center">
+ <label value="&tabIndex.label;"/>
+ <hbox>
+ <textbox id="InputTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- panels overlayed from EdImageOverlay.xul -->
+ <vbox id="imageLocation"/>
+ <vbox id="imageDimensions"/>
+ <hbox id="imageAppearance"/>
+
+ </tabpanels>
+ </tabbox>
+
+ <hbox align="end">
+ <groupbox id="imagePreview"/>
+
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+ </hbox>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInputProps.js
@@ -0,0 +1,359 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Input Tag Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var insertNew;
+var inputElement;
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ gDialog = {
+ accept: document.documentElement.getButton("accept"),
+ inputType: document.getElementById("InputType"),
+ inputNameDeck: document.getElementById("InputNameDeck"),
+ inputName: document.getElementById("InputName"),
+ inputValueDeck: document.getElementById("InputValueDeck"),
+ inputValue: document.getElementById("InputValue"),
+ inputDeck: document.getElementById("InputDeck"),
+ inputChecked: document.getElementById("InputChecked"),
+ inputSelected: document.getElementById("InputSelected"),
+ inputReadOnly: document.getElementById("InputReadOnly"),
+ inputDisabled: document.getElementById("InputDisabled"),
+ inputTabIndex: document.getElementById("InputTabIndex"),
+ inputAccessKey: document.getElementById("InputAccessKey"),
+ inputSize: document.getElementById("InputSize"),
+ inputMaxLength: document.getElementById("InputMaxLength"),
+ inputAccept: document.getElementById("InputAccept"),
+ MoreSection: document.getElementById("MoreSection"),
+ MoreFewerButton: document.getElementById("MoreFewerButton"),
+ AdvancedEditButton: document.getElementById("AdvancedEditButton"),
+ AdvancedEditDeck: document.getElementById("AdvancedEditDeck")
+ };
+
+ // Get a single selected input element
+ const kTagName = "input";
+ try {
+ inputElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
+
+ if (inputElement)
+ // We found an element and don't need to insert one
+ insertNew = false;
+ else
+ {
+ insertNew = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ inputElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
+
+ if (!inputElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+
+ var imgElement = editor.getSelectedElement("img");
+ if (imgElement)
+ {
+ // We found an image element, convert it to an input type="image"
+ inputElement.setAttribute("type", "image");
+
+ var attributes = ["src", "alt", "width", "height", "hspace", "vspace", "border", "align"];
+ for (i in attributes)
+ inputElement.setAttribute(attributes[i], imgElement.getAttribute(attributes[i]));
+ }
+ else
+ inputElement.setAttribute("value", GetSelectionAsText());
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = inputElement.cloneNode(false);
+
+ InitDialog();
+
+ InitMoreFewer();
+
+ gDialog.inputType.focus();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ var type = globalElement.getAttribute("type");
+ var index = 0;
+ switch (type)
+ {
+ case "button":
+ index = 9;
+ break;
+ case "checkbox":
+ index = 2;
+ break;
+ case "file":
+ index = 6;
+ break;
+ case "hidden":
+ index = 7;
+ break;
+ case "image":
+ index = 8;
+ break;
+ case "password":
+ index = 1;
+ break;
+ case "radio":
+ index = 3;
+ break;
+ case "reset":
+ index = 5;
+ break;
+ case "submit":
+ index = 4;
+ break;
+ }
+ gDialog.inputType.selectedIndex = index;
+ gDialog.inputName.value = globalElement.getAttribute("name");
+ gDialog.inputValue.value = globalElement.getAttribute("value");
+ gDialog.inputChecked.setAttribute("checked", globalElement.hasAttribute("checked"));
+ gDialog.inputSelected.setAttribute("checked", globalElement.hasAttribute("checked"));
+ gDialog.inputReadOnly.setAttribute("checked", globalElement.hasAttribute("readonly"));
+ gDialog.inputDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
+ gDialog.inputTabIndex.value = globalElement.getAttribute("tabindex");
+ gDialog.inputAccessKey.value = globalElement.getAttribute("accesskey");
+ gDialog.inputSize.value = globalElement.getAttribute("size");
+ gDialog.inputMaxLength.value = globalElement.getAttribute("maxlength");
+ gDialog.inputAccept.value = globalElement.getAttribute("accept");
+ SelectInputType();
+}
+
+function SelectInputType()
+{
+ var index = gDialog.inputType.selectedIndex;
+ gDialog.AdvancedEditDeck.setAttribute("selectedIndex", 0);
+ gDialog.inputNameDeck.setAttribute("selectedIndex", 0);
+ gDialog.inputValueDeck.setAttribute("selectedIndex", 0);
+ gDialog.inputValue.disabled = false;
+ gDialog.inputChecked.disabled = index != 2;
+ gDialog.inputSelected.disabled = index != 3;
+ gDialog.inputReadOnly.disabled = index > 1;
+ gDialog.inputTabIndex.disabled = index == 7;
+ gDialog.inputAccessKey.disabled = index == 7;
+ gDialog.inputSize.disabled = index > 1;
+ gDialog.inputMaxLength.disabled = index > 1;
+ gDialog.inputAccept.disabled = index != 6;
+ switch (index)
+ {
+ case 0:
+ case 1:
+ gDialog.inputValueDeck.setAttribute("selectedIndex", 1);
+ gDialog.inputDeck.setAttribute("selectedIndex", 2);
+ break;
+ case 2:
+ gDialog.inputDeck.setAttribute("selectedIndex", 0);
+ break;
+ case 3:
+ gDialog.inputDeck.setAttribute("selectedIndex", 1);
+ gDialog.inputNameDeck.setAttribute("selectedIndex", 1);
+ break;
+ case 6:
+ gDialog.inputValue.disabled = true;
+ gDialog.inputAccept.disabled = false;
+ break;
+ case 8:
+ gDialog.inputValue.disabled = true;
+ gDialog.AdvancedEditDeck.setAttribute("selectedIndex", 1);
+ gDialog.inputName.removeEventListener("input", onInput, false);
+ break;
+ case 7:
+ gDialog.inputValueDeck.setAttribute("selectedIndex", 1);
+ break;
+ }
+ onInput();
+}
+
+function onInput()
+{
+ var disabled = false;;
+ switch (gDialog.inputType.selectedIndex)
+ {
+ case 3:
+ disabled = disabled || !gDialog.inputValue.value;
+ case 4:
+ case 5:
+ break;
+ case 8:
+ disabled = !globalElement.hasAttribute("src");
+ break;
+ default:
+ disabled = !gDialog.inputName.value
+ break;
+ }
+ if (gDialog.accept.disabled != disabled)
+ {
+ gDialog.accept.disabled = disabled;
+ gDialog.AdvancedEditButton.disabled = disabled;
+ }
+}
+
+function doImageProperties()
+{
+ window.openDialog("chrome://editor/content/EdImageProps.xul",
+ "_blank", "chrome,close,titlebar,modal", globalElement);
+ window.focus();
+ onInput();
+}
+
+function ValidateData()
+{
+ var attributes = {
+ type: "",
+ name: gDialog.inputName.value,
+ value: gDialog.inputValue.value,
+ tabindex: gDialog.inputTabIndex.value,
+ accesskey: "",
+ size: "",
+ maxlength: "",
+ accept: ""
+ };
+ var index = gDialog.inputType.selectedIndex;
+ var flags = {
+ checked: false,
+ readonly: false,
+ disabled: gDialog.inputDisabled.checked
+ };
+ switch (index)
+ {
+ case 1:
+ attributes.type = "password";
+ case 0:
+ flags.readonly = gDialog.inputReadOnly.checked;
+ attributes.size = gDialog.inputSize.value;
+ attributes.maxlength = gDialog.inputMaxLength.value;
+ break;
+ case 2:
+ attributes.type = "checkbox";
+ flags.checked = gDialog.inputChecked.checked;
+ break;
+ case 3:
+ attributes.type = "radio";
+ flags.checked = gDialog.inputSelected.checked;
+ break;
+ case 4:
+ attributes.type = "submit";
+ attributes.accesskey = gDialog.inputAccessKey.value;
+ break;
+ case 5:
+ attributes.type = "reset";
+ attributes.accesskey = gDialog.inputAccessKey.value;
+ break;
+ case 6:
+ attributes.type = "file";
+ attributes.accept = gDialog.inputAccept.value;
+ attributes.value = "";
+ break;
+ case 7:
+ attributes.type = "hidden";
+ attributes.tabindex = "";
+ break;
+ case 8:
+ attributes.type = "image";
+ attributes.value = "";
+ break;
+ case 9:
+ attributes.type = "button";
+ attributes.accesskey = gDialog.inputAccessKey.value;
+ break;
+ }
+ for (var a in attributes)
+ {
+ if (attributes[a])
+ globalElement.setAttribute(a, attributes[a]);
+ else
+ globalElement.removeAttribute(a);
+ }
+ for (var f in flags)
+ {
+ if (flags[f])
+ globalElement.setAttribute(f, "");
+ else
+ globalElement.removeAttribute(f);
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ // All values are valid - copy to actual element in doc or
+ // element created to insert
+
+ var editor = GetCurrentEditor();
+
+ editor.cloneAttributes(inputElement, globalElement);
+
+ if (insertNew)
+ {
+ try {
+ // 'true' means delete the selection before inserting
+ // in case were are converting an image to an input type="image"
+ editor.insertElementAtSelection(inputElement, true);
+ } catch (e) {
+ dump(e);
+ }
+ }
+
+ SaveWindowLocation();
+
+ return true;
+ }
+ return false;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInputProps.xul
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Input Tag Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInputProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInputProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption><label control="InputType" value="&InputType.label;" accesskey="&InputType.accesskey;"/></caption>
+ <menulist id="InputType" oncommand="SelectInputType();">
+ <menupopup>
+ <menuitem label="&text.value;"/>
+ <menuitem label="&password.value;"/>
+ <menuitem label="&checkbox.value;"/>
+ <menuitem label="&radio.value;"/>
+ <menuitem label="&submit.value;"/>
+ <menuitem label="&reset.value;"/>
+ <menuitem label="&file.value;"/>
+ <menuitem label="&hidden.value;"/>
+ <menuitem label="&image.value;"/>
+ <menuitem label="&button.value;"/>
+ </menupopup>
+ </menulist>
+ </groupbox>
+
+ <groupbox><caption label="&InputSettings.label;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <deck id="InputNameDeck">
+ <label control="InputName" value="&InputName.label;" accesskey="&Name.accesskey;"/>
+ <label control="InputName" value="&GroupName.label;" accesskey="&Name.accesskey;"/>
+ </deck>
+ <textbox id="InputName" oninput="onInput();"/>
+ </row>
+ <row align="center">
+ <deck id="InputValueDeck">
+ <label control="InputValue" value="&InputValue.label;" accesskey="&Value.accesskey;"/>
+ <label control="InputValue" value="&InitialValue.label;" accesskey="&Value.accesskey;"/>
+ </deck>
+ <textbox id="InputValue" oninput="onInput();"/>
+ </row>
+ <row>
+ <spacer/>
+ <deck id="InputDeck" persist="index">
+ <checkbox id="InputChecked" label="&InputChecked.label;" accesskey="&InputChecked.accesskey;"/>
+ <checkbox id="InputSelected" label="&InputSelected.label;" accesskey="&InputSelected.accesskey;"/>
+ <checkbox id="InputReadOnly" label="&InputReadOnly.label;" accesskey="&InputReadOnly.accesskey;"/>
+ </deck>
+ </row>
+ </rows>
+ </grid>
+ <hbox>
+ <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
+ </hbox>
+ <grid id="MoreSection" align="start">
+ <columns><column/><column/></columns>
+ <rows>
+ <row>
+ <spacer/>
+ <checkbox id="InputDisabled" label="&InputDisabled.label;" accesskey="&InputDisabled.accesskey;"/>
+ </row>
+ <row align="center">
+ <label control="InputTabIndex" value="&tabIndex.label;" accesskey="&tabIndex.accesskey;"/>
+ <hbox>
+ <textbox id="InputTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="InputAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
+ <hbox>
+ <textbox id="InputAccessKey" class="narrow"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="InputSize" value="&TextSize.label;" accesskey="&TextSize.accesskey;"/>
+ <hbox>
+ <textbox id="InputSize" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="InputMaxLength" value="&TextLength.label;" accesskey="&TextLength.accesskey;"/>
+ <hbox>
+ <textbox id="InputMaxLength" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="InputAccept" value="&Accept.label;" accesskey="&Accept.accesskey;"/>
+ <textbox id="InputAccept"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <hbox flex="1" style="margin-top: 0.2em">
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <deck id="AdvancedEditDeck">
+ <button id="AdvancedEditButton"/>
+ <button label="&ImageProperties.label;" accesskey="&ImageProperties.accesskey;" oncommand="doImageProperties();"/>
+ </deck>
+ </hbox>
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsSrc.js
@@ -0,0 +1,89 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Akkana Peck (akkana@netscape.com)
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Insert Source HTML dialog */
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ document.documentElement.getButton("accept").removeAttribute("default");
+
+ // Create dialog object to store controls for easy access
+ gDialog.srcInput = document.getElementById("srcInput");
+
+ var selection;
+ try {
+ selection = editor.outputToString("text/html", kOutputFormatted | kOutputSelectionOnly | kOutputWrap);
+ } catch (e) {}
+ if (selection)
+ {
+ selection = (selection.replace(/<body[^>]*>/,"")).replace(/<\/body>/,"");
+ if (selection)
+ gDialog.srcInput.value = selection;
+ }
+ // Set initial focus
+ gDialog.srcInput.focus();
+ // Note: We can't set the caret location in a multiline textbox
+ SetWindowLocation();
+}
+
+function onAccept()
+{
+ if (gDialog.srcInput.value)
+ {
+ try {
+ GetCurrentEditor().insertHTML(gDialog.srcInput.value);
+ } catch (e) {}
+ }
+ else
+ {
+ dump("Null value -- not inserting in HTML Source dialog\n");
+ return false;
+ }
+ SaveWindowLocation();
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsSrc.xul
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertSource.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ buttonlabelaccept="&insertButton.label;"
+ buttonaccesskeyaccept="&insertButton.accesskey;"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInsSrc.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <label id="srcMessage" value="&sourceEditField.label;"/>
+ <vbox flex="1" style="width: 30em; height: 20em;">
+ <textbox id="srcInput" multiline="true" rows="1" style="width: 1em" flex="1" class="uri-element"/>
+ </vbox>
+ <!-- Will this accept the embedded HTML tags? -->
+ <hbox>
+ <spacer class="bigspacer"/>
+ <label value="&example.label;"/>
+ <label class="bold" value="&exampleOpenTag.label;"/>
+ <label class="bold italic" value="&exampleText.label;"/>
+ <label class="bold" value="&exampleCloseTag.label;"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertChars.js
@@ -0,0 +1,445 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Baki Bon <bakibon@yahoo.com> (original author)
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//------------------------------------------------------------------
+// From Unicode 3.0 Page 54. 3.11 Conjoining Jamo Behavior
+var SBase = 0xac00;
+var LBase = 0x1100;
+var VBase = 0x1161;
+var TBase = 0x11A7;
+var LCount = 19;
+var VCount = 21;
+var TCount = 28;
+var NCount = VCount * TCount;
+// End of Unicode 3.0
+
+// dialog initialization code
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+
+ StartupLatin();
+
+ // Set a variable on the opener window so we
+ // can track ownership of close this window with it
+ window.opener.InsertCharWindow = window;
+ window.sizeToContent();
+
+ SetWindowLocation();
+}
+
+function onAccept()
+{
+ // Insert the character
+ try {
+ GetCurrentEditor().insertText(LatinM.label);
+ } catch(e) {}
+
+ // Set persistent attributes to save
+ // which category, letter, and character modifier was used
+ CategoryGroup.setAttribute("category", category);
+ CategoryGroup.setAttribute("letter_index", indexL);
+ CategoryGroup.setAttribute("char_index", indexM);
+
+ // Don't close the dialog
+ return false;
+}
+
+// Don't allow inserting in HTML Source Mode
+function onFocus()
+{
+ var enable = true;
+ if ("gEditorDisplayMode" in window.opener)
+ enable = !window.opener.IsInHTMLSourceMode();
+
+ SetElementEnabled(document.documentElement.getButton("accept"), enable);
+}
+
+function onClose()
+{
+ window.opener.InsertCharWindow = null;
+ SaveWindowLocation();
+ return true;
+}
+
+//------------------------------------------------------------------
+var LatinL;
+var LatinM;
+var LatinL_Label;
+var LatinM_Label;
+var indexL=0;
+var indexM=0;
+var indexM_AU=0;
+var indexM_AL=0;
+var indexM_U=0;
+var indexM_L=0;
+var indexM_S=0;
+var LItems=0;
+var category;
+var CategoryGroup;
+var initialize = true;
+
+function StartupLatin()
+{
+
+ LatinL = document.getElementById("LatinL");
+ LatinM = document.getElementById("LatinM");
+ LatinL_Label = document.getElementById("LatinL_Label");
+ LatinM_Label = document.getElementById("LatinM_Label");
+
+ var Symbol = document.getElementById("Symbol");
+ var AccentUpper = document.getElementById("AccentUpper");
+ var AccentLower = document.getElementById("AccentLower");
+ var Upper = document.getElementById("Upper");
+ var Lower = document.getElementById("Lower");
+ CategoryGroup = document.getElementById("CatGrp");
+
+ // Initialize which radio button is set from persistent attribute...
+ var category = CategoryGroup.getAttribute("category");
+
+ // ...as well as indexes into the letter and character lists
+ var index = Number(CategoryGroup.getAttribute("letter_index"));
+ if (index && index >= 0)
+ indexL = index;
+ index = Number(CategoryGroup.getAttribute("char_index"));
+ if (index && index >= 0)
+ indexM = index;
+
+
+ switch (category)
+ {
+ case "AccentUpper": // Uppercase Diacritical
+ CategoryGroup.selectedItem = AccentUpper;
+ indexM_AU = indexM;
+ break;
+ case "AccentLower": // Lowercase Diacritical
+ CategoryGroup.selectedItem = AccentLower;
+ indexM_AL = indexM;
+ break;
+ case "Upper": // Uppercase w/o Diacritical
+ CategoryGroup.selectedItem = Upper;
+ indexM_U = indexM;
+ break;
+ case "Lower": // Lowercase w/o Diacritical
+ CategoryGroup.selectedItem = Lower;
+ indexM_L = indexM;
+ break;
+ default:
+ category = "Symbol";
+ CategoryGroup.selectedItem = Symbol;
+ indexM_S = indexM;
+ break;
+ }
+
+ ChangeCategory(category);
+ initialize = false;
+}
+
+function ChangeCategory(newCategory)
+{
+ if (category != newCategory || initialize)
+ {
+ category = newCategory;
+ // Note: Must do L before M to set LatinL.selectedIndex
+ UpdateLatinL();
+ UpdateLatinM();
+ UpdateCharacter();
+ }
+}
+
+function SelectLatinLetter()
+{
+ if(LatinL.selectedIndex != indexL )
+ {
+ indexL = LatinL.selectedIndex;
+ UpdateLatinM();
+ UpdateCharacter();
+ }
+}
+
+function SelectLatinModifier()
+{
+ if(LatinM.selectedIndex != indexM )
+ {
+ indexM = LatinM.selectedIndex;
+ UpdateCharacter();
+ }
+}
+function DisableLatinL(disable)
+{
+ if (disable) {
+ LatinL_Label.setAttribute("disabled", "true");
+ LatinL.setAttribute("disabled", "true");
+ } else {
+ LatinL_Label.removeAttribute("disabled");
+ LatinL.removeAttribute("disabled");
+ }
+}
+
+function UpdateLatinL()
+{
+ LatinL.removeAllItems();
+ if (category == "AccentUpper" || category == "AccentLower")
+ {
+ DisableLatinL(false);
+ // No Q or q
+ var alphabet = category == "AccentUpper" ? "ABCDEFGHIJKLMNOPRSTUVWXYZ" : "abcdefghijklmnoprstuvwxyz";
+ for (var letter = 0; letter < alphabet.length; letter++)
+ LatinL.appendItem(alphabet.charAt(letter));
+
+ LatinL.selectedIndex = indexL;
+ }
+ else
+ {
+ // Other categories don't hinge on a "letter"
+ DisableLatinL(true);
+ // Note: don't change the indexL so it can be used next time
+ }
+}
+
+function UpdateLatinM()
+{
+ LatinM.removeAllItems();
+ var i, accent;
+ switch(category)
+ {
+ case "AccentUpper": // Uppercase Diacritical
+ accent = upper[indexL];
+ for(i=0; i < accent.length; i++)
+ LatinM.appendItem(accent.charAt(i));
+
+ if(indexM_AU < accent.length)
+ indexM = indexM_AU;
+ else
+ indexM = accent.length - 1;
+ indexM_AU = indexM;
+ break;
+
+ case "AccentLower": // Lowercase Diacritical
+ accent = lower[indexL];
+ for(i=0; i < accent.length; i++)
+ LatinM.appendItem(accent.charAt(i));
+
+ if(indexM_AL < accent.length)
+ indexM = indexM_AL;
+ else
+ indexM = lower[indexL].length - 1;
+ indexM_AL = indexM;
+ break;
+
+ case "Upper": // Uppercase w/o Diacritical
+ for(i=0; i < otherupper.length; i++)
+ LatinM.appendItem(otherupper.charAt(i));
+
+ if(indexM_U < otherupper.length)
+ indexM = indexM_U;
+ else
+ indexM = otherupper.length - 1;
+ indexM_U = indexM;
+ break;
+
+ case "Lower": // Lowercase w/o Diacritical
+ for(i=0; i < otherlower.length; i++)
+ LatinM.appendItem(otherlower.charAt(i));
+
+ if(indexM_L < otherlower.length)
+ indexM = indexM_L;
+ else
+ indexM = otherlower.length - 1;
+ indexM_L = indexM;
+ break;
+
+ case "Symbol": // Symbol
+ for(i=0; i < symbol.length; i++)
+ LatinM.appendItem(symbol.charAt(i));
+
+ if(indexM_S < symbol.length)
+ indexM = indexM_S;
+ else
+ indexM = symbol.length - 1;
+ indexM_S = indexM;
+ break;
+ }
+ LatinM.selectedIndex = indexM;
+}
+
+function UpdateCharacter()
+{
+ indexM = LatinM.selectedIndex;
+
+ switch(category)
+ {
+ case "AccentUpper": // Uppercase Diacritical
+ indexM_AU = indexM;
+ break;
+ case "AccentLower": // Lowercase Diacritical
+ indexM_AL = indexM;
+ break;
+ case "Upper": // Uppercase w/o Diacritical
+ indexM_U = indexM;
+ break;
+ case "Lower": // Lowercase w/o Diacritical
+ indexM_L = indexM;
+ break;
+ case "Symbol":
+ indexM_S = indexM;
+ break;
+ }
+//dump("Letter Index="+indexL+", Character Index="+indexM+", Character = "+LatinM.label+"\n");
+}
+
+const upper=[
+ // A
+ "\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u0100\u0102\u0104\u01cd\u01de\u01de\u01e0\u01fa\u0200\u0202\u0226\u1e00\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6",
+ // B
+ "\u0181\u0182\u0184\u1e02\u1e04\u1e06",
+ // C
+ "\u00c7\u0106\u0108\u010a\u010c\u0187\u1e08",
+ // D
+ "\u010e\u0110\u0189\u018a\u1e0a\u1e0c\u1e0e\u1e10\u1e12",
+ // E
+ "\u00C8\u00C9\u00CA\u00CB\u0112\u0114\u0116\u0118\u011A\u0204\u0206\u0228\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6",
+ // F
+ "\u1e1e",
+ // G
+ "\u011c\u011E\u0120\u0122\u01e4\u01e6\u01f4\u1e20",
+ // H
+ "\u0124\u0126\u021e\u1e22\u1e24\u1e26\u1e28\u1e2a",
+ // I
+ "\u00CC\u00CD\u00CE\u00CF\u0128\u012a\u012C\u012e\u0130\u0208\u020a\u1e2c\u1e2e\u1ec8\u1eca",
+ // J
+ "\u0134\u01f0",
+ // K
+ "\u0136\u0198\u01e8\u1e30\u1e32\u1e34",
+ // L
+ "\u0139\u013B\u013D\u013F\u0141\u1e36\u1e38\u1e3a\u1e3c",
+ // M
+ "\u1e3e\u1e40\u1e42",
+ // N
+ "\u00D1\u0143\u0145\u0147\u014A\u01F8\u1e44\u1e46\u1e48\u1e4a",
+ // O
+ "\u00D2\u00D3\u00D4\u00D5\u00D6\u014C\u014E\u0150\u01ea\u01ec\u020c\u020e\u022A\u022C\u022E\u0230\u1e4c\u1e4e\u1e50\u1e52\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2",
+ // P
+ "\u1e54\u1e56",
+ // No Q
+ // R
+ "\u0154\u0156\u0158\u0210\u0212\u1e58\u1e5a\u1e5c\u1e5e",
+ // S
+ "\u015A\u015C\u015E\u0160\u0218\u1e60\u1e62\u1e64\u1e66\u1e68",
+ // T
+ "\u0162\u0164\u0166\u021A\u1e6a\u1e6c\u1e6e\u1e70",
+ // U
+ "\u00D9\u00DA\u00DB\u00DC\u0168\u016A\u016C\u016E\u0170\u0172\u0214\u0216\u1e72\u1e74\u1e76\u1e78\u1e7a\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0",
+ // V
+ "\u1e7c\u1e7e",
+ // W
+ "\u0174\u1e80\u1e82\u1e84\u1e86\u1e88",
+ // X
+ "\u1e8a\u1e8c",
+ // Y
+ "\u00DD\u0176\u0178\u0232\u1e8e\u1ef2\u1ef4\u1ef6\u1ef8",
+ // Z
+ "\u0179\u017B\u017D\u0224\u1e90\u1e92\u1e94"
+];
+
+const lower=[
+ // a
+ "\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u0101\u0103\u0105\u01ce\u01df\u01e1\u01fb\u0201\u0203\u0227\u1e01\u1e9a\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7",
+ // b
+ "\u0180\u0183\u0185\u1e03\u1e05\u1e07",
+ // c
+ "\u00e7\u0107\u0109\u010b\u010d\u0188\u1e09",
+ // d
+ "\u010f\u0111\u1e0b\u1e0d\u1e0f\u1e11\u1e13",
+ // e
+ "\u00e8\u00e9\u00ea\u00eb\u0113\u0115\u0117\u0119\u011b\u0205\u0207\u0229\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7",
+ // f
+ "\u1e1f",
+ // g
+ "\u011d\u011f\u0121\u0123\u01e5\u01e7\u01f5\u1e21",
+ // h
+ "\u0125\u0127\u021f\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e96",
+ // i
+ "\u00ec\u00ed\u00ee\u00ef\u0129\u012b\u012d\u012f\u0131\u01d0\u0209\u020b\u1e2d\u1e2f\u1ec9\u1ecb",
+ // j
+ "\u0135",
+ // k
+ "\u0137\u0138\u01e9\u1e31\u1e33\u1e35",
+ // l
+ "\u013a\u013c\u013e\u0140\u0142\u1e37\u1e39\u1e3b\u1e3d",
+ // m
+ "\u1e3f\u1e41\u1e43",
+ // n
+ "\u00f1\u0144\u0146\u0148\u0149\u014b\u01f9\u1e45\u1e47\u1e49\u1e4b",
+ // o
+ "\u00f2\u00f3\u00f4\u00f5\u00f6\u014d\u014f\u0151\u01d2\u01eb\u01ed\u020d\u020e\u022b\u22d\u022f\u0231\u1e4d\u1e4f\u1e51\u1e53\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3",
+ // p
+ "\u1e55\u1e57",
+ // No q
+ // r
+ "\u0155\u0157\u0159\u0211\u0213\u1e59\u1e5b\u1e5d\u1e5f",
+ // s
+ "\u015b\u015d\u015f\u0161\u0219\u1e61\u1e63\u1e65\u1e67\u1e69",
+ // t
+ "\u0162\u0163\u0165\u0167\u021b\u1e6b\u1e6d\u1e6f\u1e71\u1e97",
+ // u
+ "\u00f9\u00fa\u00fb\u00fc\u0169\u016b\u016d\u016f\u0171\u0173\u01d4\u01d6\u01d8\u01da\u01dc\u0215\u0217\u1e73\u1e75\u1e77\u1e79\u1e7b\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1",
+ // v
+ "\u1e7d\u1e7f",
+ // w
+ "\u0175\u1e81\u1e83\u1e85\u1e87\u1e89\u1e98",
+ // x
+ "\u1e8b\u1e8d",
+ // y
+ "\u00fd\u00ff\u0177\u0233\u1e8f\u1e99\u1ef3\u1ef5\u1ef7\u1ef9",
+ // z
+ "\u017a\u017c\u017e\u0225\u1e91\u1e93\u1e95"
+];
+
+
+const symbol = "\u00a1\u00a2\u00a3\u00a4\u00a5\u20ac\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00d7\u00f7";
+
+const otherupper = "\u00c6\u00d0\u00d8\u00de\u0132\u0152\u0186\u01c4\u01c5\u01c7\u01c8\u01ca\u01cb\u01F1\u01f2";
+
+const otherlower = "\u00e6\u00f0\u00f8\u00fe\u00df\u0133\u0153\u01c6\u01c9\u01cc\u01f3";
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertChars.xul
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertChars.dtd">
+
+<dialog id="insertCharsDlg" title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ onfocus = "onFocus()"
+ buttonlabelaccept="&insertButton.label;"
+ buttonlabelcancel="&closeButton.label;"
+ ondialogaccept = "return onAccept();"
+ ondialogcancel = "return onClose();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInsertChars.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <groupbox><caption label="&category.label;"/>
+ <radiogroup id="CatGrp" persist="category letter_index char_index">
+ <radio id="AccentUpper" label="&accentUpper.label;" oncommand="ChangeCategory(this.id)"/>
+ <radio id="AccentLower" label="&accentLower.label;" oncommand="ChangeCategory(this.id)"/>
+ <radio id="Upper" label="&otherUpper.label;" oncommand="ChangeCategory(this.id)"/>
+ <radio id="Lower" label="&otherLower.label;" oncommand="ChangeCategory(this.id)"/>
+ <radio id="Symbol" label="&commonSymbols.label;" oncommand="ChangeCategory(this.id)"/>
+ </radiogroup>
+ <spacer class="spacer"/>
+ </groupbox>
+ <hbox equalsize="always">
+ <vbox flex="1">
+ <!-- value is set in JS from editor.properties strings -->
+ <label id="LatinL_Label" control="LatinL" value="&letter.label;" accesskey="&letter.accessKey;"/>
+ <menulist class="larger" flex="1" id="LatinL" oncommand="SelectLatinLetter()">
+ <menupopup/>
+ </menulist>
+ </vbox>
+ <vbox flex="1">
+ <label id="LatinM_Label" control="LatinM" value="&character.label;" accesskey="&character.accessKey;"/>
+ <menulist class="larger" flex="1" id="LatinM" oncommand="SelectLatinModifier()">
+ <menupopup/>
+ </menulist>
+ </vbox>
+ </hbox>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertTOC.js
@@ -0,0 +1,411 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is TOCMaker.
+ *
+ * The Initial Developer of the Original Code is
+ * Daniel Glazman.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Daniel Glazman <daniel@glazman.org> (Original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// tocHeadersArray is the array containing the pairs tag/class
+// defining TOC entries
+var tocHeadersArray = new Array(6);
+
+// a global used when building the TOC
+var currentHeaderLevel = 0;
+
+// a global set to true if the TOC is to be readonly
+var readonly = false;
+
+// a global set to true if user wants indexes in the TOC
+var orderedList = true;
+
+// constants
+const kMozToc = "mozToc";
+const kMozTocLength = 6;
+const kMozTocIdPrefix = "mozTocId";
+const kMozTocIdPrefixLength = 8;
+const kMozTocClassPrefix = "mozToc";
+const kMozTocClassPrefixLength = 6;
+
+// Startup() is called when EdInsertTOC.xul is opened
+function Startup()
+{
+ // early way out if if we have no editor
+ if (!GetCurrentEditor()) {
+ window.close();
+ return;
+ }
+
+ var i, j;
+ // clean the table of tag/class pairs we look for
+ for (i = 0; i < 6; ++i)
+ tocHeadersArray[i] = [ "", "" ];
+
+ // reset all settings
+ for (i = 1; i < 7; ++i) {
+ var menulist = document.getElementById("header" + i + "Menulist");
+ var menuitem = document.getElementById("header" + i + "none");
+ var textbox = document.getElementById("header" + i + "Class");
+ menulist.selectedItem = menuitem;
+ textbox.setAttribute("disabled", "true");
+ }
+
+ var theDocument = GetCurrentEditor().document;
+
+ // do we already have a TOC in the document ? It should have "mozToc" ID
+ var toc = theDocument.getElementById(kMozToc);
+
+ // default TOC definition, use h1-h6 for TOC entry levels 1-6
+ var headers = "h1 1 h2 2 h3 3 h4 4 h5 5 h6 6";
+
+ var orderedListCheckbox = document.getElementById("orderedListCheckbox");
+ orderedListCheckbox.checked = true;
+
+ if (toc) {
+ // man, there is already a TOC here
+
+ if (toc.getAttribute("class") == "readonly") {
+ // and it's readonly
+ var checkbox = document.getElementById("readOnlyCheckbox");
+ checkbox.checked = true;
+ readonly = true;
+ }
+
+ // let's see if it's an OL or an UL
+ orderedList = (toc.nodeName.toLowerCase() == "ol");
+ orderedListCheckbox.checked = orderedList;
+
+ var nodeList = toc.childNodes;
+ // let's look at the children of the TOC ; if we find a comment beginning
+ // with "mozToc", it contains the TOC definition
+ for (i = 0; i< nodeList.length; ++i) {
+ if (nodeList.item(i).nodeType == Node.COMMENT_NODE &&
+ nodeList.item(i).data.substr(0, kMozTocLength) == kMozToc) {
+ // yep, there is already a definition here; parse it !
+ headers = nodeList.item(i).data.substr(kMozTocLength + 1,
+ nodeList.item(i).length - kMozTocLength - 1);
+ break;
+ }
+ }
+ }
+
+ // let's get an array filled with the (tag.class, index level) pairs
+ var headersArray = headers.split(" ");
+
+ for (i = 0; i < headersArray.length; i += 2) {
+ var tag = headersArray[i], className = "";
+ var index = headersArray[i + 1];
+ menulist = document.getElementById("header" + index + "Menulist");
+ if (menulist) {
+ var sep = tag.indexOf(".");
+ if (sep != -1) {
+ // the tag variable contains in fact "tag.className", let's parse
+ // the class and get the real tag name
+ var tmp = tag.substr(0, sep);
+ className = tag.substr(sep + 1, tag.length - sep - 1);
+ tag = tmp;
+ }
+
+ // update the dialog
+ menuitem = document.getElementById("header" + index +
+ tag.toUpperCase());
+ textbox = document.getElementById("header" + index + "Class");
+ menulist.selectedItem = menuitem;
+ if (tag != "") {
+ textbox.removeAttribute("disabled");
+ }
+ if (className != "") {
+ textbox.value = className;
+ }
+ tocHeadersArray[index - 1] = [ tag, className ];
+ }
+ }
+}
+
+
+function BuildTOC(update)
+{
+ // controlClass() is a node filter that accepts a node if
+ // (a) we don't look for a class (b) we look for a class and
+ // node has it
+ function controlClass(node, index)
+ {
+ currentHeaderLevel = index + 1;
+ if (tocHeadersArray[index][1] == "") {
+ // we are not looking for a specific class, this node is ok
+ return NodeFilter.FILTER_ACCEPT;
+ }
+ if (node.getAttribute("class")) {
+ // yep, we look for a class, let's look at all the classes
+ // the node has
+ var classArray = node.getAttribute("class").split(" ");
+ for (var j = 0; j < classArray.length; j++) {
+ if (classArray[j] == tocHeadersArray[index][1]) {
+ // hehe, we found it...
+ return NodeFilter.FILTER_ACCEPT;
+ }
+ }
+ }
+ return NodeFilter.FILTER_SKIP;
+ }
+
+ // the main node filter for our node iterator
+ // it selects the tag names as specified in the dialog
+ // then calls the controlClass filter above
+ function acceptNode(node)
+ {
+ switch (node.nodeName.toLowerCase())
+ {
+ case tocHeadersArray[0][0]:
+ return controlClass(node, 0);
+ break;
+ case tocHeadersArray[1][0]:
+ return controlClass(node, 1);
+ break;
+ case tocHeadersArray[2][0]:
+ return controlClass(node, 2);
+ break;
+ case tocHeadersArray[3][0]:
+ return controlClass(node, 3);
+ break;
+ case tocHeadersArray[4][0]:
+ return controlClass(node, 4);
+ break;
+ case tocHeadersArray[5][0]:
+ return controlClass(node, 5);
+ break;
+ default:
+ return NodeFilter.FILTER_SKIP;
+ break;
+ }
+ return NodeFilter.FILTER_SKIP; // placate the js compiler
+ }
+
+ var editor = GetCurrentEditor();
+ var theDocument = editor.document;
+ // let's create a TreeWalker to look for our nodes
+ var treeWalker = theDocument.createTreeWalker(theDocument.documentElement,
+ NodeFilter.SHOW_ELEMENT,
+ acceptNode,
+ true);
+ // we need an array to store all TOC entries we find in the document
+ var tocArray = new Array();
+ if (treeWalker) {
+ var tocSourceNode = treeWalker.nextNode();
+ while (tocSourceNode) {
+ var headerIndex = currentHeaderLevel;
+
+ // we have a node, we need to get all its textual contents
+ var textTreeWalker = theDocument.createTreeWalker(tocSourceNode,
+ NodeFilter.SHOW_TEXT,
+ null,
+ true);
+ var textNode = textTreeWalker.nextNode(), headerText = "";
+ while (textNode) {
+ headerText += textNode.data;
+ textNode = textTreeWalker.nextNode();
+ }
+
+ var anchor = tocSourceNode.firstChild, id;
+ // do we have a named anchor as 1st child of our node ?
+ if (anchor.nodeName.toLowerCase() == "a" &&
+ anchor.hasAttribute("name") &&
+ anchor.getAttribute("name").substr(0, kMozTocIdPrefixLength) == kMozTocIdPrefix) {
+ // yep, get its name
+ id = anchor.getAttribute("name");
+ }
+ else {
+ // no we don't and we need to create one
+ anchor = theDocument.createElement("a");
+ tocSourceNode.insertBefore(anchor, tocSourceNode.firstChild);
+ // let's give it a random ID
+ var c = 1000000 * Math.random();
+ id = kMozTocIdPrefix + Math.round(c);
+ anchor.setAttribute("name", id);
+ anchor.setAttribute("class", kMozTocClassPrefix +
+ tocSourceNode.nodeName.toUpperCase());
+ }
+ // and store that new entry in our array
+ tocArray.push(headerIndex, headerText, id);
+ tocSourceNode = treeWalker.nextNode();
+ }
+ }
+
+ /* generate the TOC itself */
+ headerIndex = 0;
+ var item, toc;
+ for (var i = 0; i < tocArray.length; i += 3) {
+ if (!headerIndex) {
+ // do we need to create an ol/ul container for the first entry ?
+ ++headerIndex;
+ toc = theDocument.getElementById(kMozToc);
+ if (!toc || !update) {
+ // we need to create a list container for the table of contents
+ toc = GetCurrentEditor().createElementWithDefaults(orderedList ? "ol" : "ul");
+ // grrr, we need to create a LI inside the list otherwise
+ // Composer will refuse an empty list and will remove it !
+ var pit = theDocument.createElement("li");
+ toc.appendChild(pit);
+ GetCurrentEditor().insertElementAtSelection(toc, true);
+ // ah, now it's inserted so let's remove the useless list item...
+ toc.removeChild(pit);
+ // we need to recognize later that this list is our TOC
+ toc.setAttribute("id", kMozToc);
+ }
+ else {
+ // we have to update an existing TOC, is the existing TOC of the
+ // desired type (ordered or not) ?
+ if (orderedList != (toc.nodeName.toLowerCase() == "ol")) {
+ // nope, we have to recreate the list
+ var newToc = GetCurrentEditor().createElementWithDefaults(orderedList ? "ol" : "ul");
+ toc.parentNode.insertBefore(newToc, toc);
+ // and remove the old one
+ toc.parentNode.removeChild(toc);
+ toc = newToc;
+ toc.setAttribute("id", kMozToc);
+ }
+ else {
+ // we can keep the list itself but let's get rid of the TOC entries
+ while (toc.hasChildNodes())
+ toc.removeChild(toc.lastChild);
+ }
+ }
+ var commentText = "mozToc ";
+ for (var j = 0; j < 6; j++) {
+ if (tocHeadersArray[j][0] != "") {
+ commentText += tocHeadersArray[j][0];
+ if (tocHeadersArray[j][1] != "") {
+ commentText += "." + tocHeadersArray[j][1];
+ }
+ commentText += " " + (j + 1) + " ";
+ }
+ }
+ // important, we have to remove trailing spaces
+ commentText = TrimStringRight(commentText);
+
+ // forge a comment we'll insert in the TOC ; that comment will hold
+ // the TOC definition for us
+ var ct = theDocument.createComment(commentText);
+ toc.appendChild(ct);
+
+ // assign a special class to the TOC top element if the TOC is readonly
+ // the definition of this class is in EditorOverride.css
+ if (readonly) {
+ toc.setAttribute("class", "readonly");
+ }
+ else {
+ toc.removeAttribute("class");
+ }
+
+ // We need a new variable to hold the local ul/ol container
+ // The toplevel TOC element is not the parent element of a
+ // TOC entry if its depth is > 1...
+ var tocList = toc;
+ // create a list item
+ var tocItem = theDocument.createElement("li");
+ // and an anchor in this list item
+ var tocAnchor = theDocument.createElement("a");
+ // make it target the source of the TOC entry
+ tocAnchor.setAttribute("href", "#" + tocArray[i + 2]);
+ // and put the textual contents of the TOC entry in that anchor
+ var tocEntry = theDocument.createTextNode(tocArray[i + 1]);
+ // now, insert everything where it has to be inserted
+ tocAnchor.appendChild(tocEntry);
+ tocItem.appendChild(tocAnchor);
+ tocList.appendChild(tocItem);
+ item = tocList;
+ }
+ else {
+ if (tocArray[i] < headerIndex) {
+ // if the depth of the new TOC entry is less than the depth of the
+ // last entry we created, find the good ul/ol ancestor
+ for (j = headerIndex - tocArray[i]; j > 0; --j) {
+ if (item != toc) {
+ item = item.parentNode.parentNode;
+ }
+ }
+ tocItem = theDocument.createElement("li");
+ }
+ else if (tocArray[i] > headerIndex) {
+ // to the contrary, it's deeper than the last one
+ // we need to create sub ul/ol's and li's
+ for (j = tocArray[i] - headerIndex; j > 0; --j) {
+ tocList = theDocument.createElement(orderedList ? "ol" : "ul");
+ item.lastChild.appendChild(tocList);
+ tocItem = theDocument.createElement("li");
+ tocList.appendChild(tocItem);
+ item = tocList;
+ }
+ }
+ else {
+ tocItem = theDocument.createElement("li");
+ }
+ tocAnchor = theDocument.createElement("a");
+ tocAnchor.setAttribute("href", "#" + tocArray[i + 2]);
+ tocEntry = theDocument.createTextNode(tocArray[i + 1]);
+ tocAnchor.appendChild(tocEntry);
+ tocItem.appendChild(tocAnchor);
+ item.appendChild(tocItem);
+ headerIndex = tocArray[i];
+ }
+ }
+ SaveWindowLocation();
+ return true;
+}
+
+function selectHeader(elt, index)
+{
+ var tag = elt.value;
+ tocHeadersArray[index - 1][0] = tag;
+ var textbox = document.getElementById("header" + index + "Class");
+ if (tag == "") {
+ textbox.setAttribute("disabled", "true");
+ }
+ else {
+ textbox.removeAttribute("disabled");
+ }
+}
+
+function changeClass(elt, index)
+{
+ tocHeadersArray[index - 1][1] = elt.value;
+}
+
+function ToggleReadOnlyToc(elt)
+{
+ readonly = elt.checked;
+}
+
+function ToggleOrderedList(elt)
+{
+ orderedList = elt.checked;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertTOC.xul
@@ -0,0 +1,263 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is TocMaker.
+ -
+ - The Initial Developer of the Original Code is
+ - Daniel Glazman.
+ - Portions created by the Initial Developer are Copyright (C) 2002
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Original author: Daniel Glazman (daniel@glazman.org)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertTOC.dtd">
+
+<dialog title="&Window.title;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ onload="Startup();"
+ ondialogaccept="return BuildTOC(true);"
+ oncancel="window.close(); return true;">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInsertTOC.js"/>
+ <script type="application/x-javascript" src="chrome://global/content/dialogOverlay.js" />
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <spacer id="dummy" style="display:none"/>
+ <broadcaster id="args" value=""/>
+ <vbox flex="1">
+ <groupbox><caption label="&buildToc.label;"/>
+ <grid>
+ <columns><column/><column style="min-width: 6em"/><column/></columns>
+ <rows>
+ <row align="center">
+ <spacer/>
+ <label value="&tag.label;"/>
+ <label value="&class.label;"/>
+ </row>
+ <row align="center">
+ <label value="&header1.label;"/>
+ <menulist id="header1Menulist">
+ <menupopup>
+ <menuitem id="header1none" label="--" value=""
+ oncommand="selectHeader(this, 1)"/>
+ <menuseparator/>
+ <menuitem id="header1H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1DIV" label="div" value="div"
+ oncommand="selectHeader(this, 1)"/>
+ <menuitem id="header1P" label="p" value="p"
+ oncommand="selectHeader(this, 1)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header1Class" size="10"
+ oninput="changeClass(this, 1)"/>
+ </row>
+
+ <row align="center">
+ <label value="&header2.label;"/>
+ <menulist id="header2Menulist">
+ <menupopup>
+ <menuitem id="header2none" label="--" value=""
+ oncommand="selectHeader(this, 2)"/>
+ <menuseparator/>
+ <menuitem id="header2H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2DIV" label="div" value="div"
+ oncommand="selectHeader(this, 2)"/>
+ <menuitem id="header2P" label="p" value="p"
+ oncommand="selectHeader(this, 2)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header2Class" size="10"
+ oninput="changeClass(this, 2)"/>
+ </row>
+
+ <row align="center">
+ <label value="&header3.label;"/>
+ <menulist id="header3Menulist">
+ <menupopup>
+ <menuitem id="header3none" label="--" value=""
+ oncommand="selectHeader(this, 3)"/>
+ <menuseparator/>
+ <menuitem id="header3H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3DIV" label="div" value="div"
+ oncommand="selectHeader(this, 3)"/>
+ <menuitem id="header3P" label="p" value="p"
+ oncommand="selectHeader(this, 3)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header3Class" size="10"
+ oninput="changeClass(this, 3)"/>
+ </row>
+
+ <row align="center">
+ <label value="&header4.label;"/>
+ <menulist id="header4Menulist">
+ <menupopup>
+ <menuitem id="header4none" label="--" value=""
+ oncommand="selectHeader(this, 4)"/>
+ <menuseparator/>
+ <menuitem id="header4H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4DIV" label="div" value="div"
+ oncommand="selectHeader(this, 4)"/>
+ <menuitem id="header4P" label="p" value="p"
+ oncommand="selectHeader(this, 4)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header4Class" size="10"
+ oninput="changeClass(this, 4)"/>
+ </row>
+
+ <row align="center">
+ <label value="&header5.label;"/>
+ <menulist id="header5Menulist">
+ <menupopup>
+ <menuitem id="header5none" label="--" value=""
+ oncommand="selectHeader(this, 5)"/>
+ <menuseparator/>
+ <menuitem id="header5H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5DIV" label="div" value="div"
+ oncommand="selectHeader(this, 5)"/>
+ <menuitem id="header5P" label="p" value="p"
+ oncommand="selectHeader(this, 5)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header5Class" size="10"
+ oninput="changeClass(this, 5)"/>
+ </row>
+
+ <row align="center">
+ <label value="&header6.label;"/>
+ <menulist id="header6Menulist">
+ <menupopup>
+ <menuitem id="header6none" label="--" value=""
+ oncommand="selectHeader(this, 6)"/>
+ <menuseparator/>
+ <menuitem id="header6H1" label="h1" value="h1"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6H2" label="h2" value="h2"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6H3" label="h3" value="h3"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6H4" label="h4" value="h4"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6H5" label="h5" value="h5"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6H6" label="h6" value="h6"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6DIV" label="div" value="div"
+ oncommand="selectHeader(this, 6)"/>
+ <menuitem id="header6P" label="p" value="p"
+ oncommand="selectHeader(this, 6)"/>
+ </menupopup>
+ </menulist>
+ <textbox id="header6Class" size="10"
+ oninput="changeClass(this, 6)"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+ <vbox>
+ <checkbox id="orderedListCheckbox"
+ label="&orderedList.label;"
+ oncommand="ToggleOrderedList(this)"/>
+ <checkbox id="readOnlyCheckbox"
+ label="&makeReadOnly.label;"
+ oncommand="ToggleReadOnlyToc(this)"/>
+ </vbox>
+ <separator class="groove"/>
+ </vbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertTable.js
@@ -0,0 +1,252 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//Cancel() is in EdDialogCommon.js
+var gTableElement = null;
+var gRows;
+var gColumns;
+var gActiveEditor;
+
+// dialog initialization code
+function Startup()
+{
+ gActiveEditor = GetCurrentTableEditor();
+ if (!gActiveEditor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ try {
+ gTableElement = gActiveEditor.createElementWithDefaults("table");
+ } catch (e) {}
+
+ if(!gTableElement)
+ {
+ dump("Failed to create a new table!\n");
+ window.close();
+ return;
+ }
+ gDialog.rowsInput = document.getElementById("rowsInput");
+ gDialog.columnsInput = document.getElementById("columnsInput");
+ gDialog.widthInput = document.getElementById("widthInput");
+ gDialog.borderInput = document.getElementById("borderInput");
+ gDialog.widthPixelOrPercentMenulist = document.getElementById("widthPixelOrPercentMenulist");
+ gDialog.OkButton = document.documentElement.getButton("accept");
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = gTableElement.cloneNode(false);
+ try {
+ if (GetPrefs().getBoolPref("editor.use_css") && IsHTMLEditor()
+ && !(gActiveEditor.flags & Components.interfaces.nsIPlaintextEditor.eEditorMailMask))
+ {
+ // only for Composer and not for htmlmail
+ globalElement.setAttribute("style", "text-align: left;");
+ }
+ } catch (e) {}
+
+ // Initialize all widgets with image attributes
+ InitDialog();
+
+ // Set initial number to 2 rows, 2 columns:
+ // Note, these are not attributes on the table,
+ // so don't put them in InitDialog(),
+ // else the user's values will be trashed when they use
+ // the Advanced Edit dialog
+ gDialog.rowsInput.value = 2;
+ gDialog.columnsInput.value = 2;
+
+ // If no default value on the width, set to 100%
+ if (gDialog.widthInput.value.length == 0)
+ {
+ gDialog.widthInput.value = "100";
+ gDialog.widthPixelOrPercentMenulist.selectedIndex = 1;
+ }
+
+ SetTextboxFocusById("rowsInput");
+
+ SetWindowLocation();
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitDialog()
+{
+ // Get default attributes set on the created table:
+ // Get the width attribute of the element, stripping out "%"
+ // This sets contents of menu combobox list
+ // 2nd param = null: Use current selection to find if parent is table cell or window
+ gDialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, null, "width", "widthPixelOrPercentMenulist", gPercent);
+ gDialog.borderInput.value = globalElement.getAttribute("border");
+}
+
+function ChangeRowOrColumn(id)
+{
+ // Allow only integers
+ forceInteger(id);
+
+ // Enable OK only if both rows and columns have a value > 0
+ var enable = gDialog.rowsInput.value.length > 0 &&
+ gDialog.rowsInput.value > 0 &&
+ gDialog.columnsInput.value.length > 0 &&
+ gDialog.columnsInput.value > 0;
+
+ SetElementEnabled(gDialog.OkButton, enable);
+ SetElementEnabledById("AdvancedEditButton1", enable);
+}
+
+
+// Get and validate data from widgets.
+// Set attributes on globalElement so they can be accessed by AdvancedEdit()
+function ValidateData()
+{
+ gRows = ValidateNumber(gDialog.rowsInput, null, 1, gMaxRows, null, null, true)
+ if (gValidationError)
+ return false;
+
+ gColumns = ValidateNumber(gDialog.columnsInput, null, 1, gMaxColumns, null, null, true)
+ if (gValidationError)
+ return false;
+
+ // Set attributes: NOTE: These may be empty strings (last param = false)
+ ValidateNumber(gDialog.borderInput, null, 0, gMaxPixels, globalElement, "border", false);
+ // TODO: Deal with "BORDER" without value issue
+ if (gValidationError) return false;
+
+ ValidateNumber(gDialog.widthInput, gDialog.widthPixelOrPercentMenulist,
+ 1, gMaxTableSize, globalElement, "width", false);
+ if (gValidationError)
+ return false;
+
+ return true;
+}
+
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ gActiveEditor.beginTransaction();
+ try {
+ gActiveEditor.cloneAttributes(gTableElement, globalElement);
+
+ // Create necessary rows and cells for the table
+ var tableBody = gActiveEditor.createElementWithDefaults("tbody");
+ if (tableBody)
+ {
+ gTableElement.appendChild(tableBody);
+
+ // Create necessary rows and cells for the table
+ for (var i = 0; i < gRows; i++)
+ {
+ var newRow = gActiveEditor.createElementWithDefaults("tr");
+ if (newRow)
+ {
+ tableBody.appendChild(newRow);
+ for (var j = 0; j < gColumns; j++)
+ {
+ var newCell = gActiveEditor.createElementWithDefaults("td");
+ if (newCell)
+ {
+ newRow.appendChild(newCell);
+ }
+ }
+ }
+ }
+ }
+ // Detect when entire cells are selected:
+ // Get number of cells selected
+ var tagNameObj = { value: "" };
+ var countObj = { value: 0 };
+ var element = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
+ var deletePlaceholder = false;
+
+ if (tagNameObj.value == "table")
+ {
+ //Replace entire selected table with new table, so delete the table
+ gActiveEditor.deleteTable();
+ }
+ else if (tagNameObj.value == "td")
+ {
+ if (countObj.value >= 1)
+ {
+ if (countObj.value > 1)
+ {
+ // Assume user wants to replace a block of
+ // contiguous cells with a table, so
+ // join the selected cells
+ gActiveEditor.joinTableCells(false);
+
+ // Get the cell everything was merged into
+ element = gActiveEditor.getFirstSelectedCell();
+
+ // Collapse selection into just that cell
+ gActiveEditor.selection.collapse(element,0);
+ }
+
+ if (element)
+ {
+ // Empty just the contents of the cell
+ gActiveEditor.deleteTableCellContents();
+
+ // Collapse selection to start of empty cell...
+ gActiveEditor.selection.collapse(element,0);
+ // ...but it will contain a <br> placeholder
+ deletePlaceholder = true;
+ }
+ }
+ }
+
+ // true means delete selection when inserting
+ gActiveEditor.insertElementAtSelection(gTableElement, true);
+
+ if (deletePlaceholder && gTableElement && gTableElement.nextSibling)
+ {
+ // Delete the placeholder <br>
+ gActiveEditor.deleteNode(gTableElement.nextSibling);
+ }
+ } catch (e) {}
+
+ gActiveEditor.endTransaction();
+
+ SaveWindowLocation();
+ return true;
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdInsertTable.xul
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertTable.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdInsertTable.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+ <groupbox><caption label="&size.label;"/>
+ <grid>
+ <columns>
+ <column flex="1"/>
+ <column flex="1"/>
+ <column flex="6"/>
+ </columns>
+ <rows>
+ <row align="center">
+ <label control="rowsInput" class="align-right"
+ value="&numRowsEditField.label;"
+ accesskey="&numRowsEditField.accessKey;"/>
+ <textbox class="narrow" id="rowsInput" oninput="ChangeRowOrColumn(this.id)" />
+ <spacer/>
+ </row>
+ <row align="center">
+ <label control="columnsInput" class="align-right"
+ value="&numColumnsEditField.label;"
+ accesskey="&numColumnsEditField.accessKey;"/>
+ <textbox class="narrow" id="columnsInput" oninput="ChangeRowOrColumn(this.id)" />
+ <spacer/>
+ </row>
+ <row align="center">
+ <label control="widthInput" class="align-right"
+ value="&widthEditField.label;"
+ accesskey="&widthEditField.accessKey;"/>
+ <textbox class="narrow" id="widthInput" oninput="forceInteger(this.id)" />
+ <menulist id="widthPixelOrPercentMenulist" flex="1"/>
+ <!-- child elements are appended by JS -->
+ </row>
+ </rows>
+ </grid>
+ <spacer class="spacer"/>
+ </groupbox>
+ <spacer class="spacer"/>
+ <hbox align="center">
+ <label control="borderInput" class="align-right"
+ value="&borderEditField.label;"
+ accesskey="&borderEditField.accessKey;"
+ tooltiptext="&borderEditField.tooltip;" />
+ <textbox class="narrow" id="borderInput" oninput="forceInteger(this.id)" />
+ <label value="&pixels.label;"/>
+ </hbox>
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLabelProps.js
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Label Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var labelElement;
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ gDialog.editText = document.getElementById("EditText");
+ gDialog.labelText = document.getElementById("LabelText");
+ gDialog.labelFor = document.getElementById("LabelFor");
+ gDialog.labelAccessKey = document.getElementById("LabelAccessKey");
+
+ labelElement = window.arguments[0];
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = labelElement.cloneNode(false);
+
+ InitDialog();
+
+ var range = editor.document.createRange();
+ range.selectNode(labelElement);
+ gDialog.labelText.value = range.toString();
+
+ if (/</.test(labelElement.innerHTML))
+ {
+ gDialog.editText.checked = false;
+ gDialog.editText.disabled = false;
+ gDialog.labelText.disabled = true;
+ gDialog.editText.addEventListener("command", onEditText, false);
+ SetTextboxFocus(gDialog.labelFor);
+ }
+ else
+ SetTextboxFocus(gDialog.labelText);
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ gDialog.labelFor.value = globalElement.getAttribute("for");
+ gDialog.labelAccessKey.value = globalElement.getAttribute("accesskey");
+}
+
+function onEditText()
+{
+ gDialog.editText.removeEventListener("command", onEditText, false);
+ AlertWithTitle(GetString("Alert"), GetString("EditTextWarning"));
+}
+
+function RemoveLabel()
+{
+ RemoveContainer(labelElement);
+ SaveWindowLocation();
+ window.close();
+}
+
+function ValidateData()
+{
+ if (gDialog.labelFor.value)
+ globalElement.setAttribute("for", gDialog.labelFor.value);
+ else
+ globalElement.removeAttribute("for");
+ if (gDialog.labelAccessKey.value)
+ globalElement.setAttribute("accesskey", gDialog.labelAccessKey.value);
+ else
+ globalElement.removeAttribute("accesskey");
+ return true;
+}
+
+function onAccept()
+{
+ // All values are valid - copy to actual element in doc
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ editor.beginTransaction();
+
+ try {
+ if (gDialog.editText.checked)
+ {
+ editor.setShouldTxnSetSelection(false);
+
+ while (labelElement.firstChild)
+ editor.deleteNode(labelElement.firstChild);
+ if (gDialog.labelText.value)
+ editor.insertNode(editor.document.createTextNode(gDialog.labelText.value), labelElement, 0);
+
+ editor.setShouldTxnSetSelection(true);
+ }
+
+ editor.cloneAttributes(labelElement, globalElement);
+ } catch(e) {}
+
+ editor.endTransaction();
+
+ SaveWindowLocation();
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLabelProps.xul
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Label Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorLabelProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdLabelProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&Settings.label;" accesskey="&Settings.accesskey;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <checkbox id="EditText" label="&EditLabelText.label;" accesskey="&EditLabelText.accesskey;" checked="true" disabled="true"
+ oncommand="gDialog.labelText.disabled = !gDialog.editText.checked;"/>
+ <textbox id="LabelText" accesskey="&Settings.accesskey;"/>
+ </row>
+ <row align="center">
+ <label control="LabelFor" value="&LabelFor.label;" accesskey="&LabelFor.accesskey;"/>
+ <textbox id="LabelFor"/>
+ </row>
+ <row align="center">
+ <label control="LabelAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
+ <hbox>
+ <textbox id="LabelAccessKey" class="narrow"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <hbox flex="1" style="margin-top: 0.2em">
+ <button id="RemoveLabel" label="&RemoveLabel.label;" accesskey="&RemoveLabel.accesskey;" oncommand="RemoveLabel();"/>
+ <!-- This will right-align the button -->
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLinkChecker.js
@@ -0,0 +1,234 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Akkana Peck (akkana@netscape.com)
+ * Charles Manxke (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Variables used across all the links being checked:
+var gNumLinksToCheck = 0; // The number of nsILinkCheckers
+var gLinksBeingChecked = []; // Array of nsIURICheckers
+var gURIRefObjects = []; // Array of nsIURIRefObjects
+var gNumLinksCalledBack = 0;
+var gStartedAllChecks = false;
+var gLinkCheckTimerID = 0;
+
+// Implement nsIRequestObserver:
+var gRequestObserver =
+{
+ // urichecker requires that we have an OnStartRequest even tho it's a nop.
+ onStartRequest: function(request, ctxt) { },
+
+ // onStopRequest is where we really handle the status.
+ onStopRequest: function(request, ctxt, status)
+ {
+ var linkChecker = request.QueryInterface(Components.interfaces.nsIURIChecker);
+ if (linkChecker)
+ {
+ gNumLinksCalledBack++;
+ linkChecker.status = status;
+ for (var i = 0; i < gNumLinksCalledBack; i++)
+ {
+ if (linkChecker == gLinksBeingChecked[i])
+ gLinksBeingChecked[i].status = status;
+ }
+
+ if (gStartedAllChecks && gNumLinksCalledBack >= gNumLinksToCheck)
+ {
+ clearTimeout(gLinkCheckTimerID);
+ LinkCheckTimeOut();
+ }
+ }
+ }
+}
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ // Get all objects that refer to other locations
+ var objects;
+ try {
+ objects = editor.getLinkedObjects();
+ } catch (e) {}
+
+ if (!objects || objects.Count() == 0)
+ {
+ AlertWithTitle(GetString("Alert"), GetString("NoLinksToCheck"));
+ window.close();
+ return;
+ }
+
+ gDialog.LinksList = document.getElementById("LinksList");
+
+ // Set window location relative to parent window (based on persisted attributes)
+ SetWindowLocation();
+
+
+ // Loop over the nodes that have links:
+ for (var i = 0; i < objects.Count(); i++)
+ {
+ var refobj = objects.GetElementAt(gNumLinksToCheck).QueryInterface(Components.interfaces.nsIURIRefObject);
+ // Loop over the links in this node:
+ if (refobj)
+ {
+ try {
+ var uri;
+ while ((uri = refobj.GetNextURI()))
+ {
+ // Use the real class in netlib:
+ // Note that there may be more than one link per refobj
+ gURIRefObjects[gNumLinksToCheck] = refobj;
+
+ // Make a new nsIURIChecker
+ gLinksBeingChecked[gNumLinksToCheck]
+ = Components.classes["@mozilla.org/network/urichecker;1"]
+ .createInstance()
+ .QueryInterface(Components.interfaces.nsIURIChecker);
+ // XXX uri creation needs to be localized
+ gLinksBeingChecked[gNumLinksToCheck].init(GetIOService().newURI(uri, null, null));
+ gLinksBeingChecked[gNumLinksToCheck].asyncCheck(gRequestObserver, null);
+
+ // Add item
+ var linkChecker = gLinksBeingChecked[gNumLinksToCheck].QueryInterface(Components.interfaces.nsIURIChecker);
+ SetItemStatus(linkChecker.name, "busy");
+dump(" *** Linkcount = "+gNumLinksToCheck+"\n");
+ gNumLinksToCheck++;
+
+ };
+ } catch (e) { dump (" *** EXCEPTION\n");}
+ }
+ }
+ // Done with the loop, now we can be prepared for the finish:
+ gStartedAllChecks = true;
+
+ // Start timer to limit how long we wait for link checking
+ gLinkCheckTimerID = setTimeout("LinkCheckTimeOut()", 5000);
+ window.sizeToContent();
+}
+
+function LinkCheckTimeOut()
+{
+ // We might have gotten here via a late timeout
+ if (gNumLinksToCheck <= 0)
+ return;
+ gLinkCheckTimerID = 0;
+
+ gNumLinksToCheck = 0;
+ gStartedAllChecks = false;
+ for (var i=0; i < gLinksBeingChecked.length; i++)
+ {
+ var linkChecker = gLinksBeingChecked[i].QueryInterface(Components.interfaces.nsIURIChecker);
+ // nsIURIChecker status values:
+ // NS_BINDING_SUCCEEDED link is valid
+ // NS_BINDING_FAILED link is invalid (gave an error)
+ // NS_BINDING_ABORTED timed out, or cancelled
+ switch (linkChecker.status)
+ {
+ case 0: // NS_BINDING_SUCCEEDED
+ SetItemStatus(linkChecker.name, "done");
+ break;
+ case 0x804b0001: // NS_BINDING_FAILED
+ dump(">> " + linkChecker.name + " is broken\n");
+ case 0x804b0002: // NS_BINDING_ABORTED
+// dump(">> " + linkChecker.name + " timed out\n");
+ default:
+// dump(">> " + linkChecker.name + " not checked\n");
+ SetItemStatus(linkChecker.name, "failed");
+ break;
+ }
+ }
+}
+
+// Add url to list of links to check
+// or set status for file already in the list
+// Returns true if url was in the list
+function SetItemStatus(url, status)
+{
+ if (!url)
+ return false;
+
+ if (!status)
+ status = "busy";
+
+ // Just set attribute for status icon
+ // if we already have this url
+ var listitems = document.getElementsByTagName("listitem");
+ if (listitems)
+ {
+ for (var i=0; i < listitems.length; i++)
+ {
+ if (listitems[i].getAttribute("label") == url)
+ {
+ listitems[i].setAttribute("progress", status);
+ return true;
+ }
+ }
+ }
+
+ // We're adding a new item to list
+ var listitem = document.createElementNS(XUL_NS, "listitem");
+ if (listitem)
+ {
+ listitem.setAttribute("class", "listitem-iconic progressitem");
+ // This triggers CSS to show icon for each status state
+ listitem.setAttribute("progress", status);
+ listitem.setAttribute("label", url);
+ gDialog.LinksList.appendChild(listitem);
+ }
+ return false;
+}
+
+function onAccept()
+{
+ SaveWindowLocation();
+ return true; // do close the window
+}
+
+function onCancelLinkChecker()
+{
+ if (gLinkCheckTimerID)
+ clearTimeout(gLinkCheckTimerID);
+
+/*
+ LinkCheckTimeOut();
+*/
+ return onCancel();
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLinkChecker.xul
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manske (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdLinkChecker.dtd">
+<!-- dialog containing a control requiring initial setup -->
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ buttonlabelcancel="&closeButton.label;"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancelLinkChecker();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdLinkChecker.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <listbox rows="8" id="LinksList" class="MinWidth20" flex="1"/>
+ <hbox align="center">
+ <spacer class="bigspacer"/>
+ <image class="progressitem" progress="done"/>
+ <label value="&succeeded.label;"/>
+ <spacer class="bigspacer"/>
+ <spacer class="bigspacer"/>
+ <image class="progressitem" progress="failed"/>
+ <label value="&failed.label;"/>
+ </hbox>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLinkProps.js
@@ -0,0 +1,375 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gActiveEditor;
+var anchorElement = null;
+var imageElement = null;
+var insertNew = false;
+var replaceExistingLink = false;
+var insertLinkAtCaret;
+var needLinkText = false;
+var href;
+var newLinkText;
+var gHNodeArray = {};
+var gHaveNamedAnchors = false;
+var gHaveHeadings = false;
+var gCanChangeHeadingSelected = true;
+var gCanChangeAnchorSelected = true;
+var gHaveDocumentUrl = false;
+
+// NOTE: Use "href" instead of "a" to distinguish from Named Anchor
+// The returned node is has an "a" tagName
+var tagName = "href";
+
+// dialog initialization code
+function Startup()
+{
+ gActiveEditor = GetCurrentEditor();
+ if (!gActiveEditor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+ // Message was wrapped in a <label> or <div>, so actual text is a child text node
+ gDialog.linkTextCaption = document.getElementById("linkTextCaption");
+ gDialog.linkTextMessage = document.getElementById("linkTextMessage");
+ gDialog.linkTextInput = document.getElementById("linkTextInput");
+ gDialog.hrefInput = document.getElementById("hrefInput");
+ gDialog.makeRelativeLink = document.getElementById("MakeRelativeLink");
+ gDialog.AdvancedEditSection = document.getElementById("AdvancedEdit");
+
+ // See if we have a single selected image
+ imageElement = gActiveEditor.getSelectedElement("img");
+
+ if (imageElement)
+ {
+ // Get the parent link if it exists -- more efficient than GetSelectedElement()
+ anchorElement = gActiveEditor.getElementOrParentByTagName("href", imageElement);
+ if (anchorElement)
+ {
+ if (anchorElement.childNodes.length > 1)
+ {
+ // If there are other children, then we want to break
+ // this image away by inserting a new link around it,
+ // so make a new node and copy existing attributes
+ anchorElement = anchorElement.cloneNode(false);
+ //insertNew = true;
+ replaceExistingLink = true;
+ }
+ }
+ }
+ else
+ {
+ // Get an anchor element if caret or
+ // entire selection is within the link.
+ anchorElement = gActiveEditor.getSelectedElement(tagName);
+
+ if (anchorElement)
+ {
+ // Select the entire link
+ gActiveEditor.selectElement(anchorElement);
+ }
+ else
+ {
+ // If selection starts in a link, but extends beyond it,
+ // the user probably wants to extend existing link to new selection,
+ // so check if either end of selection is within a link
+ // POTENTIAL PROBLEM: This prevents user from selecting text in an existing
+ // link and making 2 links.
+ // Note that this isn't a problem with images, handled above
+
+ anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.anchorNode);
+ if (!anchorElement)
+ anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.focusNode);
+
+ if (anchorElement)
+ {
+ // But clone it for reinserting/merging around existing
+ // link that only partially overlaps the selection
+ anchorElement = anchorElement.cloneNode(false);
+ //insertNew = true;
+ replaceExistingLink = true;
+ }
+ }
+ }
+
+ if(!anchorElement)
+ {
+ // No existing link -- create a new one
+ anchorElement = gActiveEditor.createElementWithDefaults(tagName);
+ insertNew = true;
+ // Hide message about removing existing link
+ //document.getElementById("RemoveLinkMsg").hidden = true;
+ }
+ if(!anchorElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+
+ // We insert at caret only when nothing is selected
+ insertLinkAtCaret = gActiveEditor.selection.isCollapsed;
+
+ var selectedText;
+ if (insertLinkAtCaret)
+ {
+ // Groupbox caption:
+ gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
+
+ // Message above input field:
+ gDialog.linkTextMessage.setAttribute("value", GetString("EnterLinkText"));
+ gDialog.linkTextMessage.setAttribute("accesskey", GetString("EnterLinkTextAccessKey"));
+ }
+ else
+ {
+ if (!imageElement)
+ {
+ // We get here if selection is exactly around a link node
+ // Check if selection has some text - use that first
+ selectedText = GetSelectionAsText();
+ if (!selectedText)
+ {
+ // No text, look for first image in the selection
+ var children = anchorElement.childNodes;
+ if (children)
+ {
+ for(var i=0; i < children.length; i++)
+ {
+ var nodeName = children.item(i).nodeName.toLowerCase();
+ if (nodeName == "img")
+ {
+ imageElement = children.item(i);
+ break;
+ }
+ }
+ }
+ }
+ }
+ // Set "caption" for link source and the source text or image URL
+ if (imageElement)
+ {
+ gDialog.linkTextCaption.setAttribute("label", GetString("LinkImage"));
+ // Link source string is the source URL of image
+ // TODO: THIS DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
+ gDialog.linkTextMessage.setAttribute("value", imageElement.src);
+ } else {
+ gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
+ if (selectedText)
+ {
+ // Use just the first 60 characters and add "..."
+ gDialog.linkTextMessage.setAttribute("value", TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 60, true));
+ } else {
+ gDialog.linkTextMessage.setAttribute("value", GetString("MixedSelection"));
+ }
+ }
+ }
+
+ // Make a copy to use for AdvancedEdit and onSaveDefault
+ globalElement = anchorElement.cloneNode(false);
+
+ // Get the list of existing named anchors and headings
+ FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
+
+ // We only need to test for this once per dialog load
+ gHaveDocumentUrl = GetDocumentBaseUrl();
+
+ // Set data for the dialog controls
+ InitDialog();
+
+ // Search for a URI pattern in the selected text
+ // as candidate href
+ selectedText = TrimString(selectedText);
+ if (!gDialog.hrefInput.value && TextIsURI(selectedText))
+ gDialog.hrefInput.value = selectedText;
+
+ // Set initial focus
+ if (insertLinkAtCaret) {
+ // We will be using the HREF inputbox, so text message
+ SetTextboxFocus(gDialog.linkTextInput);
+ } else {
+ SetTextboxFocus(gDialog.hrefInput);
+
+ // We will not insert a new link at caret, so remove link text input field
+ gDialog.linkTextInput.hidden = true;
+ gDialog.linkTextInput = null;
+ }
+
+ // This sets enable state on OK button
+ doEnabling();
+
+ SetWindowLocation();
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitDialog()
+{
+ // Must use getAttribute, not "globalElement.href",
+ // or foreign chars aren't coverted correctly!
+ gDialog.hrefInput.value = globalElement.getAttribute("href");
+
+ // Set "Relativize" checkbox according to current URL state
+ SetRelativeCheckbox(gDialog.makeRelativeLink);
+}
+
+function doEnabling()
+{
+ // We disable Ok button when there's no href text only if inserting a new link
+ var enable = insertNew ? (TrimString(gDialog.hrefInput.value).length > 0) : true;
+
+ // anon. content, so can't use SetElementEnabledById here
+ var dialogNode = document.getElementById("linkDlg");
+ dialogNode.getButton("accept").disabled = !enable;
+
+ SetElementEnabledById( "AdvancedEditButton1", enable);
+}
+
+function ChangeLinkLocation()
+{
+ SetRelativeCheckbox(gDialog.makeRelativeLink);
+ // Set OK button enable state
+ doEnabling();
+}
+
+// Get and validate data from widgets.
+// Set attributes on globalElement so they can be accessed by AdvancedEdit()
+function ValidateData()
+{
+ href = TrimString(gDialog.hrefInput.value);
+ if (href)
+ {
+ // Set the HREF directly on the editor document's anchor node
+ // or on the newly-created node if insertNew is true
+ globalElement.setAttribute("href",href);
+ }
+ else if (insertNew)
+ {
+ // We must have a URL to insert a new link
+ //NOTE: We accept an empty HREF on existing link to indicate removing the link
+ ShowInputErrorMessage(GetString("EmptyHREFError"));
+ return false;
+ }
+ if (gDialog.linkTextInput)
+ {
+ // The text we will insert isn't really an attribute,
+ // but it makes sense to validate it
+ newLinkText = TrimString(gDialog.linkTextInput.value);
+ if (!newLinkText)
+ {
+ if (href)
+ newLinkText = href
+ else
+ {
+ ShowInputErrorMessage(GetString("EmptyLinkTextError"));
+ SetTextboxFocus(gDialog.linkTextInput);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ if (href.length > 0)
+ {
+ // Copy attributes to element we are changing or inserting
+ gActiveEditor.cloneAttributes(anchorElement, globalElement);
+
+ // Coalesce into one undo transaction
+ gActiveEditor.beginTransaction();
+
+ // Get text to use for a new link
+ if (insertLinkAtCaret)
+ {
+ // Append the link text as the last child node
+ // of the anchor node
+ var textNode = gActiveEditor.document.createTextNode(newLinkText);
+ if (textNode)
+ anchorElement.appendChild(textNode);
+ try {
+ gActiveEditor.insertElementAtSelection(anchorElement, false);
+ } catch (e) {
+ dump("Exception occured in InsertElementAtSelection\n");
+ return true;
+ }
+ } else if (insertNew || replaceExistingLink)
+ {
+ // Link source was supplied by the selection,
+ // so insert a link node as parent of this
+ // (may be text, image, or other inline content)
+ try {
+ gActiveEditor.insertLinkAroundSelection(anchorElement);
+ } catch (e) {
+ dump("Exception occured in InsertElementAtSelection\n");
+ return true;
+ }
+ }
+ // Check if the link was to a heading
+ if (href in gHNodeArray)
+ {
+ var anchorNode = gActiveEditor.createElementWithDefaults("a");
+ if (anchorNode)
+ {
+ anchorNode.name = href.substr(1);
+
+ // Insert the anchor into the document,
+ // but don't let the transaction change the selection
+ gActiveEditor.setShouldTxnSetSelection(false);
+ gActiveEditor.insertNode(anchorNode, gHNodeArray[href], 0);
+ gActiveEditor.setShouldTxnSetSelection(true);
+ }
+ }
+ gActiveEditor.endTransaction();
+ }
+ else if (!insertNew)
+ {
+ // We already had a link, but empty HREF means remove it
+ EditorRemoveTextProperty("href", "");
+ }
+ SaveWindowLocation();
+ return true;
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdLinkProps.xul
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorLinkProperties.dtd">
+
+<dialog id="linkDlg" title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ buttons="accept,cancel"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdLinkProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <vbox style="min-width: 20em">
+ <groupbox><caption id="linkTextCaption"/>
+ <vbox>
+ <label id="linkTextMessage" control="linkTextInput"/>
+ <textbox id="linkTextInput"/>
+ </vbox>
+ </groupbox>
+
+ <groupbox id="LinkURLBox"><caption label="&LinkURLBox.label;"/>
+ <vbox id="LinkLocationBox"/>
+ <!-- mail compose will insert custom item here defined in mailComposeEditorOverlay.xul -->
+ </groupbox>
+ </vbox>
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdListProps.js
@@ -0,0 +1,478 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ * Ryan Cassin (rcassin@supernova.org)
+ * David Turley (dturley@pobox.com) contributed Roman Numeral conversion code.
+ * Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//Cancel() is in EdDialogCommon.js
+var gBulletStyleType = "";
+var gNumberStyleType = "";
+var gListElement;
+var gOriginalListType = "";
+var gListType = "";
+var gMixedListSelection = false;
+var gStyleType = "";
+var gOriginalStyleType = "";
+const gOnesArray = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
+const gTensArray = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"];
+const gHundredsArray = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"];
+const gThousandsArray = ["", "M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM", "MMMMMMMMM"];
+const gRomanDigits = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000};
+const A = "A".charCodeAt(0);
+const gArabic = "1";
+const gUpperRoman = "I";
+const gLowerRoman = "i";
+const gUpperLetters = "A";
+const gLowerLetters = "a";
+const gDecimalCSS = "decimal";
+const gUpperRomanCSS = "upper-roman";
+const gLowerRomanCSS = "lower-roman";
+const gUpperAlphaCSS = "upper-alpha";
+const gLowerAlphaCSS = "lower-alpha";
+
+// dialog initialization code
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+ gDialog.ListTypeList = document.getElementById("ListType");
+ gDialog.BulletStyleList = document.getElementById("BulletStyle");
+ gDialog.BulletStyleLabel = document.getElementById("BulletStyleLabel");
+ gDialog.StartingNumberInput = document.getElementById("StartingNumber");
+ gDialog.StartingNumberLabel = document.getElementById("StartingNumberLabel");
+ gDialog.AdvancedEditButton = document.getElementById("AdvancedEditButton1");
+ gDialog.RadioGroup = document.getElementById("RadioGroup");
+ gDialog.ChangeAllRadio = document.getElementById("ChangeAll");
+ gDialog.ChangeSelectedRadio = document.getElementById("ChangeSelected");
+
+ // Try to get an existing list(s)
+ var mixedObj = { value: null };
+ try {
+ gListType = editor.getListState(mixedObj, {}, {}, {} );
+
+ // We may have mixed list and non-list, or > 1 list type in selection
+ gMixedListSelection = mixedObj.value;
+
+ // Get the list element at the anchor node
+ gListElement = editor.getElementOrParentByTagName("list", null);
+ } catch (e) {}
+
+ // The copy to use in AdvancedEdit
+ if (gListElement)
+ globalElement = gListElement.cloneNode(false);
+
+ // Show extra options for changing entire list if we have one already.
+ gDialog.RadioGroup.collapsed = !gListElement;
+ if (gListElement)
+ {
+ // Radio button index is persistent
+ if (gDialog.RadioGroup.getAttribute("index") == "1")
+ gDialog.RadioGroup.selectedItem = gDialog.ChangeSelectedRadio;
+ else
+ gDialog.RadioGroup.selectedItem = gDialog.ChangeAllRadio;
+ }
+
+ InitDialog();
+
+ gOriginalListType = gListType;
+
+ gDialog.ListTypeList.focus();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ // Note that if mixed, we we pay attention
+ // only to the anchor node's list type
+ // (i.e., don't confuse user with "mixed" designation)
+ if (gListElement)
+ gListType = gListElement.nodeName.toLowerCase();
+ else
+ gListType = "";
+
+ gDialog.ListTypeList.value = gListType;
+ gDialog.StartingNumberInput.value = "";
+
+ // Last param = true means attribute value is case-sensitive
+ var type = globalElement ? GetHTMLOrCSSStyleValue(globalElement, "type", "list-style-type") : null;
+
+ var index = 0;
+ if (gListType == "ul")
+ {
+ if (type)
+ {
+ type = type.toLowerCase();
+ gBulletStyleType = type;
+ gOriginalStyleType = type;
+ }
+ }
+ else if (gListType == "ol")
+ {
+ // Translate CSS property strings
+ switch (type.toLowerCase())
+ {
+ case gDecimalCSS:
+ type = gArabic;
+ break;
+ case gUpperRomanCSS:
+ type = gUpperRoman;
+ break;
+ case gLowerRomanCSS:
+ type = gLowerRoman;
+ break;
+ case gUpperAlphaCSS:
+ type = gUpperLetters;
+ break;
+ case gLowerAlphaCSS:
+ type = gLowerLetters;
+ break;
+ }
+ if (type)
+ {
+ gNumberStyleType = type;
+ gOriginalStyleType = type;
+ }
+
+ // Convert attribute number to appropriate letter or roman numeral
+ gDialog.StartingNumberInput.value =
+ ConvertStartAttrToUserString(globalElement.getAttribute("start"), type);
+ }
+ BuildBulletStyleList();
+}
+
+// Convert attribute number to appropriate letter or roman numeral
+function ConvertStartAttrToUserString(startAttr, type)
+{
+ switch (type)
+ {
+ case gUpperRoman:
+ startAttr = ConvertArabicToRoman(startAttr);
+ break;
+ case gLowerRoman:
+ startAttr = ConvertArabicToRoman(startAttr).toLowerCase();
+ break;
+ case gUpperLetters:
+ startAttr = ConvertArabicToLetters(startAttr);
+ break;
+ case gLowerLetters:
+ startAttr = ConvertArabicToLetters(startAttr).toLowerCase();
+ break;
+ }
+ return startAttr;
+}
+
+function BuildBulletStyleList()
+{
+ gDialog.BulletStyleList.removeAllItems();
+ var label;
+
+ if (gListType == "ul")
+ {
+ gDialog.BulletStyleList.removeAttribute("disabled");
+ gDialog.BulletStyleLabel.removeAttribute("disabled");
+ gDialog.StartingNumberInput.setAttribute("disabled", "true");
+ gDialog.StartingNumberLabel.setAttribute("disabled", "true");
+
+ label = GetString("BulletStyle");
+
+ gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
+ gDialog.BulletStyleList.appendItem(GetString("SolidCircle"), "disc");
+ gDialog.BulletStyleList.appendItem(GetString("OpenCircle"), "circle");
+ gDialog.BulletStyleList.appendItem(GetString("SolidSquare"), "square");
+
+ gDialog.BulletStyleList.value = gBulletStyleType;
+ }
+ else if (gListType == "ol")
+ {
+ gDialog.BulletStyleList.removeAttribute("disabled");
+ gDialog.BulletStyleLabel.removeAttribute("disabled");
+ gDialog.StartingNumberInput.removeAttribute("disabled");
+ gDialog.StartingNumberLabel.removeAttribute("disabled");
+ label = GetString("NumberStyle");
+
+ gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
+ gDialog.BulletStyleList.appendItem(GetString("Style_1"), gArabic);
+ gDialog.BulletStyleList.appendItem(GetString("Style_I"), gUpperRoman);
+ gDialog.BulletStyleList.appendItem(GetString("Style_i"), gLowerRoman);
+ gDialog.BulletStyleList.appendItem(GetString("Style_A"), gUpperLetters);
+ gDialog.BulletStyleList.appendItem(GetString("Style_a"), gLowerLetters);
+
+ gDialog.BulletStyleList.value = gNumberStyleType;
+ }
+ else
+ {
+ gDialog.BulletStyleList.setAttribute("disabled", "true");
+ gDialog.BulletStyleLabel.setAttribute("disabled", "true");
+ gDialog.StartingNumberInput.setAttribute("disabled", "true");
+ gDialog.StartingNumberLabel.setAttribute("disabled", "true");
+ }
+
+ // Disable advanced edit button if changing to "normal"
+ if (gListType)
+ gDialog.AdvancedEditButton.removeAttribute("disabled");
+ else
+ gDialog.AdvancedEditButton.setAttribute("disabled", "true");
+
+ if (label)
+ gDialog.BulletStyleLabel.setAttribute("label",label);
+}
+
+function SelectListType()
+{
+ // Each list type is stored in the "value" of each menuitem
+ var NewType = gDialog.ListTypeList.value;
+
+ if (NewType == "ol")
+ SetTextboxFocus(gDialog.StartingNumberInput);
+
+ if (gListType != NewType)
+ {
+ gListType = NewType;
+
+ // Create a newlist object for Advanced Editing
+ try {
+ if (gListType)
+ globalElement = GetCurrentEditor().createElementWithDefaults(gListType);
+ } catch (e) {}
+
+ BuildBulletStyleList();
+ }
+}
+
+function SelectBulletStyle()
+{
+ // Save the selected index so when user changes
+ // list style, restore index to associated list
+ // Each bullet or number type is stored in the "value" of each menuitem
+ if (gListType == "ul")
+ gBulletStyleType = gDialog.BulletStyleList.value;
+ else if (gListType == "ol")
+ {
+ var type = gDialog.BulletStyleList.value;
+ if (gNumberStyleType != type)
+ {
+ // Convert existing input value to attr number first,
+ // then convert to the appropriate format for the newly-selected
+ gDialog.StartingNumberInput.value =
+ ConvertStartAttrToUserString( ConvertUserStringToStartAttr(gNumberStyleType), type);
+
+ gNumberStyleType = type;
+ SetTextboxFocus(gDialog.StartingNumberInput);
+ }
+ }
+}
+
+function ValidateData()
+{
+ gBulletStyleType = gDialog.BulletStyleList.value;
+ // globalElement should already be of the correct type
+
+ if (globalElement)
+ {
+ var editor = GetCurrentEditor();
+ if (gListType == "ul")
+ {
+ if (gBulletStyleType && gDialog.ChangeAllRadio.selected)
+ globalElement.setAttribute("type", gBulletStyleType);
+ else
+ try {
+ editor.removeAttributeOrEquivalent(globalElement, "type", true);
+ } catch (e) {}
+
+ }
+ else if (gListType == "ol")
+ {
+ if (gBulletStyleType)
+ globalElement.setAttribute("type", gBulletStyleType);
+ else
+ try {
+ editor.removeAttributeOrEquivalent(globalElement, "type", true);
+ } catch (e) {}
+
+ var startingNumber = ConvertUserStringToStartAttr(gBulletStyleType);
+ if (startingNumber)
+ globalElement.setAttribute("start", startingNumber);
+ else
+ globalElement.removeAttribute("start");
+ }
+ }
+ return true;
+}
+
+function ConvertUserStringToStartAttr(type)
+{
+ var startingNumber = TrimString(gDialog.StartingNumberInput.value);
+
+ switch (type)
+ {
+ case gUpperRoman:
+ case gLowerRoman:
+ // If the input isn't an integer, assume it's a roman numeral. Convert it.
+ if (!Number(startingNumber))
+ startingNumber = ConvertRomanToArabic(startingNumber);
+ break;
+ case gUpperLetters:
+ case gLowerLetters:
+ // Get the number equivalent of the letters
+ if (!Number(startingNumber))
+ startingNumber = ConvertLettersToArabic(startingNumber);
+ break;
+ }
+ return startingNumber;
+}
+
+function ConvertRomanToArabic(num)
+{
+ num = num.toUpperCase();
+ if (num && !/[^MDCLXVI]/i.test(num))
+ {
+ var Arabic = 0;
+ var last_digit = 1000;
+ for (var i=0; i < num.length; i++)
+ {
+ var digit = gRomanDigits[num.charAt(i)];
+ if (last_digit < digit)
+ Arabic -= 2 * last_digit;
+
+ last_digit = digit;
+ Arabic += last_digit;
+ }
+ return Arabic;
+ }
+
+ return "";
+}
+
+function ConvertArabicToRoman(num)
+{
+ if (/^\d{1,4}$/.test(num))
+ {
+ var digits = ("000" + num).substr(-4);
+ return gThousandsArray[digits.charAt(0)] +
+ gHundredsArray[digits.charAt(1)] +
+ gTensArray[digits.charAt(2)] +
+ gOnesArray[digits.charAt(3)];
+ }
+ return "";
+}
+
+function ConvertLettersToArabic(letters)
+{
+ letters = letters.toUpperCase();
+ if (!letters || /[^A-Z]/.test(letters))
+ return "";
+
+ var num = 0;
+ for (var i = 0; i < letters.length; i++)
+ num = num * 26 + letters.charCodeAt(i) - A + 1;
+ return num;
+}
+
+function ConvertArabicToLetters(num)
+{
+ var letters = "";
+ while (num) {
+ num--;
+ letters = String.fromCharCode(A + (num % 26)) + letters;
+ num = Math.floor(num / 26);
+ }
+ return letters;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ // Coalesce into one undo transaction
+ var editor = GetCurrentEditor();
+
+ editor.beginTransaction();
+
+ var changeEntireList = gDialog.RadioGroup.selectedItem == gDialog.ChangeAllRadio;
+
+ // Remember which radio button was selected
+ if (gListElement)
+ gDialog.RadioGroup.setAttribute("index", changeEntireList ? "0" : "1");
+
+ var changeList;
+ if (gListElement && gDialog.ChangeAllRadio.selected)
+ {
+ changeList = true;
+ }
+ else
+ changeList = gMixedListSelection || gListType != gOriginalListType ||
+ gBulletStyleType != gOriginalStyleType;
+ if (changeList)
+ {
+ try {
+ if (gListType)
+ {
+ editor.makeOrChangeList(gListType, changeEntireList,
+ (gBulletStyleType != gOriginalStyleType) ? gBulletStyleType : null);
+
+ // Get the new list created:
+ gListElement = editor.getElementOrParentByTagName(gListType, null);
+
+ editor.cloneAttributes(gListElement, globalElement);
+ }
+ else
+ {
+ // Remove all existing lists
+ if (gListElement && changeEntireList)
+ editor.selectElement(gListElement);
+
+ editor.removeList("ol");
+ editor.removeList("ul");
+ editor.removeList("dl");
+ }
+ } catch (e) {}
+ }
+
+ editor.endTransaction();
+
+ SaveWindowLocation();
+
+ return true;
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdListProps.xul
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manske (cmanske@netscape.com)
+ - Ryan Cassin (rcassin@supernova.org)
+ - Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorListProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdListProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox flex="1"><caption label="&ListType.label;"/>
+ <menulist id="ListType" oncommand="SelectListType()">
+ <menupopup>
+ <menuitem label="&none.value;"/>
+ <menuitem value="ul" label="&bulletList.value;"/>
+ <menuitem value="ol" label="&numberList.value;"/>
+ <menuitem value="dl" label="&definitionList.value;"/>
+ </menupopup>
+ </menulist>
+ </groupbox>
+ <spacer class="spacer"/>
+
+ <!-- message text and list items are set in JS
+ text value should be identical to string with id=BulletStyle in editor.properties
+ -->
+ <groupbox flex="1"><caption id="BulletStyleLabel" label="&bulletStyle.label;"/>
+ <menulist class="MinWidth10em" id="BulletStyle" oncommand="SelectBulletStyle()">
+ <menupopup/>
+ </menulist>
+ <spacer class="spacer"/>
+ <hbox>
+ <label id="StartingNumberLabel" control="StartingNumber"
+ value="&startingNumber.label;" accesskey="&startingNumber.accessKey;"/>
+ <textbox class="narrow" id="StartingNumber"/>
+ <spacer/>
+ </hbox>
+ </groupbox>
+ <radiogroup id="RadioGroup" index="0" persist="index">
+ <radio id="ChangeAll" label="&changeEntireListRadio.label;" accesskey="&changeEntireListRadio.accessKey;"/>
+ <radio id="ChangeSelected" label="&changeSelectedRadio.label;" accesskey="&changeSelectedRadio.accessKey;"/>
+ </radiogroup>
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdNamedAnchorProps.js
@@ -0,0 +1,197 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gInsertNew = true;
+var gAnchorElement = null;
+var gOriginalName = "";
+const kTagName = "anchor";
+
+// dialog initialization code
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ gDialog.OkButton = document.documentElement.getButton("accept");
+ gDialog.NameInput = document.getElementById("nameInput");
+
+ // Get a single selected element of the desired type
+ gAnchorElement = editor.getSelectedElement(kTagName);
+
+ if (gAnchorElement) {
+ // We found an element and don't need to insert one
+ gInsertNew = false;
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = gAnchorElement.cloneNode(false);
+ gOriginalName = ConvertToCDATAString(gAnchorElement.name);
+ } else {
+ gInsertNew = true;
+ // We don't have an element selected,
+ // so create one with default attributes
+ gAnchorElement = editor.createElementWithDefaults(kTagName);
+ if (gAnchorElement) {
+ // Use the current selection as suggested name
+ var name = GetSelectionAsText();
+ // Get 40 characters of the selected text and don't add "...",
+ // replace whitespace with "_" and strip non-word characters
+ name = ConvertToCDATAString(TruncateStringAtWordEnd(name, 40, false));
+ //Be sure the name is unique to the document
+ if (AnchorNameExists(name))
+ name += "_"
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = gAnchorElement.cloneNode(false);
+ globalElement.setAttribute("name",name);
+ }
+ }
+ if(!gAnchorElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+
+ InitDialog();
+
+ DoEnabling();
+ SetTextboxFocus(gDialog.NameInput);
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ gDialog.NameInput.value = globalElement.getAttribute("name");
+}
+
+function ChangeName()
+{
+ if (gDialog.NameInput.value.length > 0)
+ {
+ // Replace spaces with "_" and strip other non-URL characters
+ // Note: we could use ConvertAndEscape, but then we'd
+ // have to UnEscapeAndConvert beforehand - too messy!
+ gDialog.NameInput.value = ConvertToCDATAString(gDialog.NameInput.value);
+ }
+ DoEnabling();
+}
+
+function DoEnabling()
+{
+ var enable = gDialog.NameInput.value.length > 0;
+ SetElementEnabled(gDialog.OkButton, enable);
+ SetElementEnabledById("AdvancedEditButton1", enable);
+}
+
+function AnchorNameExists(name)
+{
+ var anchorList;
+ try {
+ anchorList = GetCurrentEditor().document.anchors;
+ } catch (e) {}
+
+ if (anchorList) {
+ for (var i = 0; i < anchorList.length; i++) {
+ if (anchorList[i].name == name)
+ return true;
+ }
+ }
+ return false;
+}
+
+// Get and validate data from widgets.
+// Set attributes on globalElement so they can be accessed by AdvancedEdit()
+function ValidateData()
+{
+ var name = TrimString(gDialog.NameInput.value);
+ if (!name)
+ {
+ ShowInputErrorMessage(GetString("MissingAnchorNameError"));
+ SetTextboxFocus(gDialog.NameInput);
+ return false;
+ } else {
+ // Replace spaces with "_" and strip other characters
+ // Note: we could use ConvertAndEscape, but then we'd
+ // have to UnConverAndEscape beforehand - too messy!
+ name = ConvertToCDATAString(name);
+
+ if (gOriginalName != name && AnchorNameExists(name))
+ {
+ ShowInputErrorMessage(GetString("DuplicateAnchorNameError").replace(/%name%/,name));
+ SetTextboxFocus(gDialog.NameInput);
+ return false;
+ }
+ globalElement.name = name;
+ }
+ return true;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ if (gOriginalName != globalElement.name)
+ {
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ // "false" = don't delete selected text when inserting
+ if (gInsertNew)
+ {
+ // We must insert element before copying CSS style attribute,
+ // but we must set the name else it won't insert at all
+ gAnchorElement.name = globalElement.name;
+ editor.insertElementAtSelection(gAnchorElement, false);
+ }
+
+ // Copy attributes to element we are changing or inserting
+ editor.cloneAttributes(gAnchorElement, globalElement);
+
+ } catch (e) {}
+
+ editor.endTransaction();
+ }
+ SaveWindowLocation();
+ return true;
+ }
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdNamedAnchorProps.xul
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdNamedAnchorProperties.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdNamedAnchorProps.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <label control="nameInput"
+ value="&anchorNameEditField.label;"
+ accesskey="&anchorNameEditField.accessKey;"/>
+ <textbox class="MinWidth20em" id="nameInput" oninput="ChangeName()"
+ tooltiptext="&nameInput.tooltip;"/>
+ <spacer class="spacer"/>
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdPageProps.js
@@ -0,0 +1,202 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gNewTitle = "";
+var gAuthor = "";
+var gDescription = "";
+var gAuthorElement;
+var gDescriptionElement;
+var gInsertNewAuthor = false;
+var gInsertNewDescription = false;
+var gTitleWasEdited = false;
+var gAuthorWasEdited = false;
+var gDescWasEdited = false;
+
+//Cancel() is in EdDialogCommon.js
+// dialog initialization code
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ gDialog.PageLocation = document.getElementById("PageLocation");
+ gDialog.PageModDate = document.getElementById("PageModDate");
+ gDialog.TitleInput = document.getElementById("TitleInput");
+ gDialog.AuthorInput = document.getElementById("AuthorInput");
+ gDialog.DescriptionInput = document.getElementById("DescriptionInput");
+
+ // Default string for new page is set from DTD string in XUL,
+ // so set only if not new doc URL
+ var location = GetDocumentUrl();
+ var lastmodString = GetString("Unknown");
+
+ if (!IsUrlAboutBlank(location))
+ {
+ // NEVER show username and password in clear text
+ gDialog.PageLocation.setAttribute("value", StripPassword(location));
+
+ // Get last-modified file date+time
+ // TODO: Convert this to local time?
+ var lastmod;
+ try {
+ lastmod = editor.document.lastModified; // get string of last modified date
+ } catch (e) {}
+ // Convert modified string to date (0 = unknown date or January 1, 1970 GMT)
+ if(Date.parse(lastmod))
+ {
+ try {
+ const nsScriptableDateFormat_CONTRACTID = "@mozilla.org/intl/scriptabledateformat;1";
+ const nsIScriptableDateFormat = Components.interfaces.nsIScriptableDateFormat;
+ var dateService = Components.classes[nsScriptableDateFormat_CONTRACTID]
+ .getService(nsIScriptableDateFormat);
+
+ var lastModDate = new Date();
+ lastModDate.setTime(Date.parse(lastmod));
+ lastmodString = dateService.FormatDateTime("",
+ dateService.dateFormatLong,
+ dateService.timeFormatSeconds,
+ lastModDate.getFullYear(),
+ lastModDate.getMonth()+1,
+ lastModDate.getDate(),
+ lastModDate.getHours(),
+ lastModDate.getMinutes(),
+ lastModDate.getSeconds());
+ } catch (e) {}
+ }
+ }
+ gDialog.PageModDate.value = lastmodString;
+
+ gAuthorElement = GetMetaElement("author");
+ if (!gAuthorElement)
+ {
+ gAuthorElement = CreateMetaElement("author");
+ if (!gAuthorElement)
+ {
+ window.close();
+ return;
+ }
+ gInsertNewAuthor = true;
+ }
+
+ gDescriptionElement = GetMetaElement("description");
+ if (!gDescriptionElement)
+ {
+ gDescriptionElement = CreateMetaElement("description");
+ if (!gDescriptionElement)
+ window.close();
+
+ gInsertNewDescription = true;
+ }
+
+ InitDialog();
+
+ SetTextboxFocus(gDialog.TitleInput);
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ gDialog.TitleInput.value = GetDocumentTitle();
+
+ var gAuthor = TrimString(gAuthorElement.getAttribute("content"));
+ if (!gAuthor)
+ {
+ // Fill in with value from editor prefs
+ var prefs = GetPrefs();
+ if (prefs)
+ gAuthor = prefs.getCharPref("editor.author");
+ }
+ gDialog.AuthorInput.value = gAuthor;
+ gDialog.DescriptionInput.value = gDescriptionElement.getAttribute("content");
+}
+
+function TextboxChanged(ID)
+{
+ switch(ID)
+ {
+ case "TitleInput":
+ gTitleWasEdited = true;
+ break;
+ case "AuthorInput":
+ gAuthorWasEdited = true;
+ break;
+ case "DescriptionInput":
+ gDescWasEdited = true;
+ break;
+ }
+}
+
+function ValidateData()
+{
+ gNewTitle = TrimString(gDialog.TitleInput.value);
+ gAuthor = TrimString(gDialog.AuthorInput.value);
+ gDescription = TrimString(gDialog.DescriptionInput.value);
+ return true;
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ // Set title contents even if string is empty
+ // because TITLE is a required HTML element
+ if (gTitleWasEdited)
+ SetDocumentTitle(gNewTitle);
+
+ if (gAuthorWasEdited)
+ SetMetaElementContent(gAuthorElement, gAuthor, gInsertNewAuthor, false);
+
+ if (gDescWasEdited)
+ SetMetaElementContent(gDescriptionElement, gDescription, gInsertNewDescription, false);
+
+ editor.endTransaction();
+
+ SaveWindowLocation();
+ return true; // do close the window
+ }
+ return false;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdPageProps.xul
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPageProperties.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdPageProps.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+ <grid>
+ <columns><column flex="1"/><column flex="2"/></columns>
+ <rows>
+ <row>
+ <label value="&location.label;"/>
+ <label value="&locationNewPage.label;" id="PageLocation"/>
+ </row>
+ <row>
+ <label value="&lastModified.label;"/>
+ <label id="PageModDate"/>
+ </row>
+ <spacer class="spacer"/>
+ <row align="center">
+ <label value="&titleInput.label;" accesskey="&titleInput.accessKey;" control="TitleInput"/>
+ <textbox class="MinWidth20em" id="TitleInput" oninput="TextboxChanged(this.id)"/>
+ </row>
+ <row align="center">
+ <label value="&authorInput.label;" accesskey="&authorInput.accessKey;" control="AuthorInput"/>
+ <textbox class="MinWidth20em" id="AuthorInput" oninput="TextboxChanged(this.id)"/>
+ </row>
+ <row align="center">
+ <label value="&descriptionInput.label;" accesskey="&descriptionInput.accessKey;" control="DescriptionInput"/>
+ <textbox class="MinWidth20em" id="DescriptionInput" oninput="TextboxChanged(this.id)"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer class="bigspacer"/>
+ <label value="&EditHEADSource1.label;"/>
+ <description class="wrap" flex="1">&EditHEADSource2.label;</description>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdReplace.js
@@ -0,0 +1,415 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Kin Blas <kin@netscape.com>
+ * Akkana Peck <akkana@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gReplaceDialog; // Quick access to document/form elements.
+var gFindInst; // nsIWebBrowserFind that we're going to use
+var gFindService; // Global service which remembers find params
+var gEditor; // the editor we're using
+
+function initDialogObject()
+{
+ // Create gReplaceDialog object and initialize.
+ gReplaceDialog = {};
+ gReplaceDialog.findInput = document.getElementById("dialog.findInput");
+ gReplaceDialog.replaceInput = document.getElementById("dialog.replaceInput");
+ gReplaceDialog.caseSensitive = document.getElementById("dialog.caseSensitive");
+ gReplaceDialog.wrap = document.getElementById("dialog.wrap");
+ gReplaceDialog.searchBackwards = document.getElementById("dialog.searchBackwards");
+ gReplaceDialog.findNext = document.getElementById("findNext");
+ gReplaceDialog.replace = document.getElementById("replace");
+ gReplaceDialog.replaceAndFind = document.getElementById("replaceAndFind");
+ gReplaceDialog.replaceAll = document.getElementById("replaceAll");
+}
+
+function loadDialog()
+{
+ // Set initial dialog field contents.
+ // Set initial dialog field contents. Use the gFindInst attributes first,
+ // this is necessary for window.find()
+ gReplaceDialog.findInput.value = (gFindInst.searchString
+ ? gFindInst.searchString
+ : gFindService.searchString);
+ gReplaceDialog.replaceInput.value = gFindService.replaceString;
+ gReplaceDialog.caseSensitive.checked = (gFindInst.matchCase
+ ? gFindInst.matchCase
+ : gFindService.matchCase);
+ gReplaceDialog.wrap.checked = (gFindInst.wrapFind
+ ? gFindInst.wrapFind
+ : gFindService.wrapFind);
+ gReplaceDialog.searchBackwards.checked = (gFindInst.findBackwards
+ ? gFindInst.findBackwards
+ : gFindService.findBackwards);
+
+ doEnabling();
+}
+
+function onLoad()
+{
+ // Get the xul <editor> element:
+ var editorElement = window.arguments[0];
+
+ // If we don't get the editor, then we won't allow replacing.
+ gEditor = editorElement.getEditor(editorElement.contentWindow);
+ if (!gEditor)
+ {
+ window.close();
+ return;
+ }
+
+ // Get the nsIWebBrowserFind service:
+ gFindInst = editorElement.webBrowserFind;
+
+ try {
+ // get the find service, which stores global find state
+ gFindService = Components.classes["@mozilla.org/find/find_service;1"]
+ .getService(Components.interfaces.nsIFindService);
+ } catch(e) { dump("No find service!\n"); gFindService = 0; }
+
+ // Init gReplaceDialog.
+ initDialogObject();
+
+ // Change "OK" to "Find".
+ //dialog.find.label = document.getElementById("fBLT").getAttribute("label");
+
+ // Fill dialog.
+ loadDialog();
+
+ if (gReplaceDialog.findInput.value)
+ gReplaceDialog.findInput.select();
+ else
+ gReplaceDialog.findInput.focus();
+}
+
+function onUnload() {
+ // Disconnect context from this dialog.
+ gFindReplaceData.replaceDialog = null;
+}
+
+function saveFindData()
+{
+ // Set data attributes per user input.
+ if (gFindService)
+ {
+ gFindService.searchString = gReplaceDialog.findInput.value;
+ gFindService.matchCase = gReplaceDialog.caseSensitive.checked;
+ gFindService.wrapFind = gReplaceDialog.wrap.checked;
+ gFindService.findBackwards = gReplaceDialog.searchBackwards.checked;
+ }
+}
+
+function setUpFindInst()
+{
+ gFindInst.searchString = gReplaceDialog.findInput.value;
+ gFindInst.matchCase = gReplaceDialog.caseSensitive.checked;
+ gFindInst.wrapFind = gReplaceDialog.wrap.checked;
+ gFindInst.findBackwards = gReplaceDialog.searchBackwards.checked;
+}
+
+function onFindNext()
+{
+ // Transfer dialog contents to the find service.
+ saveFindData();
+ // set up the find instance
+ setUpFindInst();
+
+ // Search.
+ var result = gFindInst.findNext();
+
+ if (!result)
+ {
+ var bundle = document.getElementById("findBundle");
+ AlertWithTitle(null, bundle.getString("notFoundWarning"));
+ SetTextboxFocus(gReplaceDialog.findInput);
+ gReplaceDialog.findInput.select();
+ gReplaceDialog.findInput.focus();
+ return false;
+ }
+ return true;
+}
+
+function onReplace()
+{
+ if (!gEditor)
+ return false;
+
+ // Does the current selection match the find string?
+ var selection = gEditor.selection;
+
+ var selStr = selection.toString();
+ var specStr = gReplaceDialog.findInput.value;
+ if (!gReplaceDialog.caseSensitive.checked)
+ {
+ selStr = selStr.toLowerCase();
+ specStr = specStr.toLowerCase();
+ }
+ // Unfortunately, because of whitespace we can't just check
+ // whether (selStr == specStr), but have to loop ourselves.
+ // N chars of whitespace in specStr can match any M >= N in selStr.
+ var matches = true;
+ var specLen = specStr.length;
+ var selLen = selStr.length;
+ if (selLen < specLen)
+ matches = false;
+ else
+ {
+ var specArray = specStr.match(/\S+|\s+/g);
+ var selArray = selStr.match(/\S+|\s+/g);
+ if ( specArray.length != selArray.length)
+ matches = false;
+ else
+ {
+ for (var i=0; i<selArray.length; i++)
+ {
+ if (selArray[i] != specArray[i])
+ {
+ if ( /\S/.test(selArray[i][0]) || /\S/.test(specArray[i][0]) )
+ {
+ // not a space chunk -- match fails
+ matches = false;
+ break;
+ }
+ else if ( selArray[i].length < specArray[i].length )
+ {
+ // if it's a space chunk then we only care that sel be
+ // at least as long as spec
+ matches = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // If the current selection doesn't match the pattern,
+ // then we want to find the next match, but not do the replace.
+ // That's what most other apps seem to do.
+ // So here, just return.
+ if (!matches)
+ return false;
+
+ // Transfer dialog contents to the find service.
+ saveFindData();
+
+ // For reverse finds, need to remember the caret position
+ // before current selection
+ var newRange;
+ if (gReplaceDialog.searchBackwards.checked && selection.rangeCount > 0)
+ {
+ newRange = selection.getRangeAt(0).cloneRange();
+ newRange.collapse(true);
+ }
+
+ // nsPlaintextEditor::InsertText fails if the string is empty,
+ // so make that a special case:
+ var replStr = gReplaceDialog.replaceInput.value;
+ if (replStr == "")
+ gEditor.deleteSelection(0);
+ else
+ gEditor.insertText(replStr);
+
+ // For reverse finds, need to move caret just before the replaced text
+ if (gReplaceDialog.searchBackwards.checked && newRange)
+ {
+ gEditor.selection.removeAllRanges();
+ gEditor.selection.addRange(newRange);
+ }
+
+ return true;
+}
+
+function onReplaceAll()
+{
+ if (!gEditor)
+ return;
+
+ var findStr = gReplaceDialog.findInput.value;
+ var repStr = gReplaceDialog.replaceInput.value;
+
+ // Transfer dialog contents to the find service.
+ saveFindData();
+
+ var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance().QueryInterface(Components.interfaces.nsIFind);
+
+ finder.caseSensitive = gReplaceDialog.caseSensitive.checked;
+ finder.findBackwards = gReplaceDialog.searchBackwards.checked;
+
+ // We want the whole operation to be undoable in one swell foop,
+ // so start a transaction:
+ gEditor.beginTransaction();
+
+ // and to make sure we close the transaction, guard against exceptions:
+ try {
+ // Make a range containing the current selection,
+ // so we don't go past it when we wrap.
+ var selection = gEditor.selection;
+ var selecRange;
+ if (selection.rangeCount > 0)
+ selecRange = selection.getRangeAt(0);
+ var origRange = selecRange.cloneRange();
+
+ // We'll need a range for the whole document:
+ var wholeDocRange = gEditor.document.createRange();
+ var rootNode = gEditor.rootElement.QueryInterface(Components.interfaces.nsIDOMNode);
+ wholeDocRange.selectNodeContents(rootNode);
+
+ // And start and end points:
+ var endPt = gEditor.document.createRange();
+
+ if (gReplaceDialog.searchBackwards.checked)
+ {
+ endPt.setStart(wholeDocRange.startContainer, wholeDocRange.startOffset);
+ endPt.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
+ }
+ else
+ {
+ endPt.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
+ endPt.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
+ }
+
+ // Find and replace from here to end (start) of document:
+ var foundRange;
+ var searchRange = wholeDocRange.cloneRange();
+ while ((foundRange = finder.Find(findStr, searchRange,
+ selecRange, endPt)) != null)
+ {
+ gEditor.selection.removeAllRanges();
+ gEditor.selection.addRange(foundRange);
+
+ // The editor will leave the caret at the end of the replaced text.
+ // For reverse finds, we need it at the beginning,
+ // so save the next position now.
+ if (gReplaceDialog.searchBackwards.checked)
+ {
+ selecRange = foundRange.cloneRange();
+ selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
+ }
+
+ // nsPlaintextEditor::InsertText fails if the string is empty,
+ // so make that a special case:
+ if (repStr == "")
+ gEditor.deleteSelection(0);
+ else
+ gEditor.insertText(repStr);
+
+ // If we're going forward, we didn't save selecRange before, so do it now:
+ if (!gReplaceDialog.searchBackwards.checked)
+ {
+ selection = gEditor.selection;
+ if (selection.rangeCount <= 0) {
+ gEditor.endTransaction();
+ return;
+ }
+ selecRange = selection.getRangeAt(0).cloneRange();
+ }
+ }
+
+ // If no wrapping, then we're done
+ if (!gReplaceDialog.wrap.checked) {
+ gEditor.endTransaction();
+ return;
+ }
+
+ // If wrapping, find from start/end of document back to start point.
+ if (gReplaceDialog.searchBackwards.checked)
+ {
+ // Collapse origRange to end
+ origRange.setStart(origRange.endContainer, origRange.endOffset);
+ // Set current position to document end
+ selecRange.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
+ selecRange.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
+ }
+ else
+ {
+ // Collapse origRange to start
+ origRange.setEnd(origRange.startContainer, origRange.startOffset);
+ // Set current position to document start
+ selecRange.setStart(wholeDocRange.startContainer,
+ wholeDocRange.startOffset);
+ selecRange.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
+ }
+
+ while ((foundRange = finder.Find(findStr, wholeDocRange,
+ selecRange, origRange)) != null)
+ {
+ gEditor.selection.removeAllRanges();
+ gEditor.selection.addRange(foundRange);
+
+ // Save insert point for backward case
+ if (gReplaceDialog.searchBackwards.checked)
+ {
+ selecRange = foundRange.cloneRange();
+ selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
+ }
+
+ // nsPlaintextEditor::InsertText fails if the string is empty,
+ // so make that a special case:
+ if (repStr == "")
+ gEditor.deleteSelection(0);
+ else
+ gEditor.insertText(repStr);
+
+ // Get insert point for forward case
+ if (!gReplaceDialog.searchBackwards.checked)
+ {
+ selection = gEditor.selection;
+ if (selection.rangeCount <= 0) {
+ gEditor.endTransaction();
+ return;
+ }
+ selecRange = selection.getRangeAt(0);
+ }
+ }
+ } // end try
+ catch (e) { }
+
+ gEditor.endTransaction();
+}
+
+function doEnabling()
+{
+ var findStr = gReplaceDialog.findInput.value;
+ var repStr = gReplaceDialog.replaceInput.value;
+ gReplaceDialog.enabled = findStr;
+ gReplaceDialog.findNext.disabled = !findStr;
+ gReplaceDialog.replace.disabled = !findStr;
+ gReplaceDialog.replaceAndFind.disabled = !findStr;
+ gReplaceDialog.replaceAll.disabled = !findStr;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdReplace.xul
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 1998-1999
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ Kin Blas <kin@netscape.com>
+ Akkana Peck <akkana@netscape.com>
+
+ Alternatively, the contents of this file may be used under the terms of
+ either of the GNU General Public License Version 2 or later (the "GPL"),
+ or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorReplace.dtd">
+
+<dialog id="replaceDlg" title="&replaceDialog.title;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ persist="screenX screenY"
+ buttons="cancel"
+ onload = "onLoad()"
+ ondialogaccept="return onFindNext();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdReplace.js"/>
+ <stringbundle id="findBundle" src="chrome://global/locale/finddialog.properties"/>
+
+ <hbox>
+ <vbox>
+ <spacer class="spacer"/>
+ <grid align="start">
+ <columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label value="&findField.label;" accesskey="&findField.accesskey;" control="dialog.findInput"/>
+ <textbox id="dialog.findInput" oninput="doEnabling();"/>
+ </row>
+ <row align="center">
+ <label value="&replaceField.label;" accesskey="&replaceField.accesskey;" control="dialog.replaceInput"/>
+ <textbox id="dialog.replaceInput" oninput="doEnabling();"/>
+ </row>
+ <row align="start">
+ <spacer/>
+ <vbox align="start">
+ <spacer class="bigspacer"/>
+ <checkbox id="dialog.caseSensitive" label="&caseSensitiveCheckbox.label;"
+ accesskey="&caseSensitiveCheckbox.accesskey;"/>
+ <checkbox id="dialog.wrap" label="&wrapCheckbox.label;"
+ accesskey="&wrapCheckbox.accesskey;"/>
+ <checkbox id="dialog.searchBackwards" label="&backwardsCheckbox.label;"
+ accesskey="&backwardsCheckbox.accesskey;"/>
+ </vbox>
+ </row>
+ </rows>
+ </grid>
+ </vbox>
+ <vbox>
+ <button id="findNext" label="&findNextButton.label;" accesskey="&findNextButton.accesskey;"
+ oncommand="onFindNext();" default="true"/>
+ <button id="replace" label="&replaceButton.label;" accesskey="&replaceButton.accesskey;"
+ oncommand="onReplace();"/>
+ <button id="replaceAndFind" label="&replaceAndFindButton.label;"
+ accesskey="&replaceAndFindButton.accesskey;" oncommand="onReplace(); onFindNext();"/>
+ <button id="replaceAll" label="&replaceAllButton.label;"
+ accesskey="&replaceAllButton.accesskey;" oncommand="onReplaceAll();"/>
+ <button dlgtype="cancel" label="&closeButton.label;"/>
+ </vbox>
+ </hbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSelectProps.js
@@ -0,0 +1,790 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Selection List Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Global variables
+
+var atomService = Components.classes["@mozilla.org/atom-service;1"]
+ .getService(Components.interfaces.nsIAtomService);
+var checkedAtoms = {
+ "false": atomService.getAtom("checked-false"),
+ "true": atomService.getAtom("checked-true")};
+
+var hasValue;
+var oldValue;
+var insertNew;
+var itemArray;
+var treeBoxObject;
+var treeSelection;
+var selectElement;
+var currentItem = null;
+var selectedOption = null;
+var selectedOptionCount = 0;
+
+// Utility functions
+
+function getParentIndex(index)
+{
+ switch (itemArray[index].level)
+ {
+ case 0: return -1;
+ case 1: return 0;
+ }
+ while (itemArray[--index].level > 1);
+ return index;
+}
+
+function UpdateSelectMultiple()
+{
+ if (selectedOptionCount > 1)
+ {
+ gDialog.selectMultiple.checked = true;
+ gDialog.selectMultiple.disabled = true;
+ }
+ else
+ gDialog.selectMultiple.disabled = false;
+}
+
+/* wrapper objects:
+ * readonly attribute Node element; // DOM node (select/optgroup/option)
+ * readonly attribute int level; // tree depth
+ * readonly attribute boolean container; // can contain options
+ * string getCellText(string col); // tree view helper
+ * string cycleCell(int currentIndex); // tree view helper
+ * void onFocus(); // load data into deck
+ * void onBlur(); // save data from deck
+ * boolean canDestroy(boolean prompt); // NB prompt not used
+ * void destroy(); // post remove callback
+ * void moveUp();
+ * boolean canMoveDown();
+ * void moveDown();
+ * void appendOption(newElement, currentIndex);
+ */
+
+// OPTION element wrapper object
+
+// Create a wrapper for the given element at the given level
+function optionObject(option, level)
+{
+ // select an added option (when loading from document)
+ if (option.hasAttribute("selected"))
+ selectedOptionCount++;
+ this.level = level;
+ this.element = option;
+}
+
+optionObject.prototype.container = false;
+
+optionObject.prototype.getCellText = function getCellText(column)
+{
+ if (column.id == "SelectSelCol")
+ return "";
+ if (column.id == "SelectValCol" && this.element.hasAttribute("value"))
+ return this.element.getAttribute("value");
+ return this.element.text;
+}
+
+optionObject.prototype.cycleCell = function cycleCell(index)
+{
+ if (this.element.hasAttribute("selected"))
+ {
+ this.element.removeAttribute("selected");
+ selectedOptionCount--;
+ selectedOption = null;
+ }
+ else
+ {
+ // Different handling for multiselect lists
+ if (gDialog.selectMultiple.checked || !selectedOption)
+ selectedOptionCount++;
+ else if (selectedOption)
+ {
+ selectedOption.removeAttribute("selected");
+ var column = treeBoxObject.columns["SelectSelCol"];
+ treeBoxObject.invalidateColumn(column);
+ selectedOption = null;
+ }
+ this.element.setAttribute("selected", "");
+ selectedOption = this.element;
+ var column = treeBoxObject.columns["SelectSelCol"];
+ treeBoxObject.invalidateCell(index, column);
+ }
+ if (currentItem == this)
+ // Also update the deck
+ gDialog.optionSelected.setAttribute("checked", this.element.hasAttribute("selected"));
+ UpdateSelectMultiple();
+};
+
+optionObject.prototype.onFocus = function onFocus()
+{
+ gDialog.optionText.value = this.element.text;
+ hasValue = this.element.hasAttribute("value");
+ oldValue = this.element.value;
+ gDialog.optionHasValue.checked = hasValue;
+ gDialog.optionValue.value = hasValue ? this.element.value : this.element.text;
+ gDialog.optionSelected.checked = this.element.hasAttribute("selected");
+ gDialog.optionDisabled.checked = this.element.hasAttribute("disabled");
+ gDialog.selectDeck.setAttribute("selectedIndex", "2");
+};
+
+optionObject.prototype.onBlur = function onBlur()
+{
+ this.element.text = gDialog.optionText.value;
+ if (gDialog.optionHasValue.checked)
+ this.element.value = gDialog.optionValue.value;
+ else
+ this.element.removeAttribute("value");
+ if (gDialog.optionSelected.checked)
+ this.element.setAttribute("selected", "");
+ else
+ this.element.removeAttribute("selected");
+ if (gDialog.optionDisabled.checked)
+ this.element.setAttribute("disabled", "");
+ else
+ this.element.removeAttribute("disabled");
+};
+
+optionObject.prototype.canDestroy = function canDestroy(prompt)
+{
+ return true;
+/*return !prompt ||
+ ConfirmWithTitle(GetString("DeleteOption"),
+ GetString("DeleteOptionMsg"),
+ GetString("DeleteOption"));*/
+};
+
+optionObject.prototype.destroy = function destroy()
+{
+ // Deselect a removed option
+ if (this.element.hasAttribute("selected"))
+ {
+ selectedOptionCount--;
+ selectedOption = null;
+ UpdateSelectMultiple();
+ }
+};
+
+/* 4 cases:
+ * a) optgroup -> optgroup
+ * ... ...
+ * option option
+ * b) optgroup -> option
+ * option optgroup
+ * ... ...
+ * c) option
+ * option
+ * d) option
+ * option
+ */
+
+optionObject.prototype.moveUp = function moveUp()
+{
+ var i;
+ var index = treeSelection.currentIndex;
+ if (itemArray[index].level < itemArray[index - 1].level + itemArray[index - 1].container)
+ {
+ // we need to repaint the tree's lines
+ treeBoxObject.invalidateRange(getParentIndex(index), index);
+ // a) option is just after an optgroup, so it becomes the last child
+ itemArray[index].level = 2;
+ treeBoxObject.view.selectionChanged();
+ }
+ else
+ {
+ // otherwise new option level is now the same as the previous item
+ itemArray[index].level = itemArray[index - 1].level;
+ // swap the option with the previous item
+ itemArray.splice(index, 0, itemArray.splice(--index, 1)[0]);
+ }
+ selectTreeIndex(index, true);
+}
+
+optionObject.prototype.canMoveDown = function canMoveDown()
+{
+ // move down is not allowed on the last option if its level is 1
+ return this.level > 1 || itemArray.length - treeSelection.currentIndex > 1;
+}
+
+optionObject.prototype.moveDown = function moveDown()
+{
+ var i;
+ var index = treeSelection.currentIndex;
+ if (index + 1 == itemArray.length || itemArray[index].level > itemArray[index + 1].level)
+ {
+ // we need to repaint the tree's lines
+ treeBoxObject.invalidateRange(getParentIndex(index), index);
+ // a) option is last child of an optgroup, so it moves just after
+ itemArray[index].level = 1;
+ treeBoxObject.view.selectionChanged();
+ }
+ else
+ {
+ // level increases if the option was preceding an optgroup
+ itemArray[index].level += itemArray[index + 1].container;
+ // swap the option with the next item
+ itemArray.splice(index, 0, itemArray.splice(++index, 1)[0]);
+ }
+ selectTreeIndex(index, true);
+}
+
+optionObject.prototype.appendOption = function appendOption(child, parent)
+{
+ // special case quick check
+ if (this.level == 1)
+ return gDialog.appendOption(child, 0);
+
+ // append the option to the parent element
+ parent = getParentIndex(parent);
+ return itemArray[parent].appendOption(child, parent);
+};
+
+// OPTGROUP element wrapper object
+
+function optgroupObject(optgroup)
+{
+ this.element = optgroup;
+}
+
+optgroupObject.prototype.level = 1;
+
+optgroupObject.prototype.container = true;
+
+optgroupObject.prototype.getCellText = function getCellText(column)
+{
+ return column.id == "SelectTextCol" ? this.element.label : "";
+}
+
+optgroupObject.prototype.cycleCell = function cycleCell(index)
+{
+};
+
+optgroupObject.prototype.onFocus = function onFocus()
+{
+ gDialog.optgroupLabel.value = this.element.label;
+ gDialog.optgroupDisabled.checked = this.element.disabled;
+ gDialog.selectDeck.setAttribute("selectedIndex", "1");
+};
+
+optgroupObject.prototype.onBlur = function onBlur()
+{
+ this.element.label = gDialog.optgroupLabel.value;
+ this.element.disabled = gDialog.optgroupDisabled.checked;
+};
+
+optgroupObject.prototype.canDestroy = function canDestroy(prompt)
+{
+ // Only removing empty option groups for now
+ return gDialog.nextChild(treeSelection.currentIndex) - treeSelection.currentIndex == 1;
+/*&& (!prompt ||
+ ConfirmWithTitle(GetString("DeleteOptGroup"),
+ GetString("DeleteOptGroupMsg"),
+ GetString("DeleteOptGroup")));
+*/
+};
+
+optgroupObject.prototype.destroy = function destroy()
+{
+};
+
+optgroupObject.prototype.moveUp = function moveUp()
+{
+ // Find the index of the previous and next elements at the same level
+ var index = treeSelection.currentIndex;
+ var i = index;
+ while (itemArray[--index].level > 1);
+ var j = gDialog.nextChild(i);
+ // Cut out the element, cut the array in two, then join together
+ var movedItems = itemArray.splice(i, j - i);
+ var endItems = itemArray.splice(index);
+ itemArray = itemArray.concat(movedItems).concat(endItems);
+ // Repaint the lot
+ treeBoxObject.invalidateRange(index, j);
+ selectTreeIndex(index, true);
+}
+
+optgroupObject.prototype.canMoveDown = function canMoveDown()
+{
+ return gDialog.lastChild() > treeSelection.currentIndex;
+}
+
+optgroupObject.prototype.moveDown = function moveDown()
+{
+ // Find the index of the next two elements at the same level
+ var index = treeSelection.currentIndex;
+ var i = gDialog.nextChild(index);
+ var j = gDialog.nextChild(i);
+ // Cut out the element, cut the array in two, then join together
+ var movedItems = itemArray.splice(i, j - 1);
+ var endItems = itemArray.splice(index);
+ itemArray = itemArray.concat(movedItems).concat(endItems);
+ // Repaint the lot
+ treeBoxObject.invalidateRange(index, j);
+ index += j - i;
+ selectTreeIndex(index, true);
+}
+
+optgroupObject.prototype.appendOption = function appendOption(child, parent)
+{
+ var index = gDialog.nextChild(parent);
+ // XXX need to repaint the lines, tree won't do this
+ var primaryCol = treeBoxObject.getPrimaryColumn();
+ treeBoxObject.invalidateCell(index - 1, primaryCol);
+ // insert the wrapped object as the last child
+ itemArray.splice(index, 0, new optionObject(child, 2));
+ treeBoxObject.rowCountChanged(index, 1);
+ selectTreeIndex(index, false);
+};
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ // Get a single selected select element
+ const kTagName = "select";
+ try {
+ selectElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
+
+ if (selectElement)
+ // We found an element and don't need to insert one
+ insertNew = false;
+ else
+ {
+ insertNew = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ selectElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
+
+ if(!selectElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ }
+
+ // SELECT element wrapper object
+ gDialog = {
+ // useful elements
+ accept: document.documentElement.getButton("accept"),
+ selectDeck: document.getElementById("SelectDeck"),
+ selectName: document.getElementById("SelectName"),
+ selectSize: document.getElementById("SelectSize"),
+ selectMultiple: document.getElementById("SelectMultiple"),
+ selectDisabled: document.getElementById("SelectDisabled"),
+ selectTabIndex: document.getElementById("SelectTabIndex"),
+ optgroupLabel: document.getElementById("OptGroupLabel"),
+ optgroupDisabled: document.getElementById("OptGroupDisabled"),
+ optionText: document.getElementById("OptionText"),
+ optionHasValue: document.getElementById("OptionHasValue"),
+ optionValue: document.getElementById("OptionValue"),
+ optionSelected: document.getElementById("OptionSelected"),
+ optionDisabled: document.getElementById("OptionDisabled"),
+ removeButton: document.getElementById("RemoveButton"),
+ previousButton: document.getElementById("PreviousButton"),
+ nextButton: document.getElementById("NextButton"),
+ tree: document.getElementById("SelectTree"),
+ // wrapper methods (except MoveUp and MoveDown)
+ element: selectElement.cloneNode(false),
+ level: 0,
+ container: true,
+ getCellText: function getCellText(column)
+ {
+ return column.id == "SelectTextCol" ? this.element.getAttribute("name") : "";
+ },
+ cycleCell: function cycleCell(index) {},
+ onFocus: function onFocus()
+ {
+ gDialog.selectName.value = this.element.getAttribute("name");
+ gDialog.selectSize.value = this.element.getAttribute("size");
+ gDialog.selectMultiple.checked = this.element.hasAttribute("multiple");
+ gDialog.selectDisabled.checked = this.element.hasAttribute("disabled");
+ gDialog.selectTabIndex.value = this.element.getAttribute("tabindex");
+ this.selectDeck.setAttribute("selectedIndex", "0");
+ onNameInput();
+ },
+ onBlur: function onBlur()
+ {
+ this.element.setAttribute("name", gDialog.selectName.value);
+ if (gDialog.selectSize.value)
+ this.element.setAttribute("size", gDialog.selectSize.value);
+ else
+ this.element.removeAttribute("size");
+ if (gDialog.selectMultiple.checked)
+ this.element.setAttribute("multiple", "");
+ else
+ this.element.removeAttribute("multiple");
+ if (gDialog.selectDisabled.checked)
+ this.element.setAttribute("disabled", "");
+ else
+ this.element.removeAttribute("disabled");
+ if (gDialog.selectTabIndex.value)
+ this.element.setAttribute("tabindex", gDialog.selectTabIndex.value);
+ else
+ this.element.removeAttribute("tabindex");
+ },
+ appendOption: function appendOption(child, parent)
+ {
+ var index = itemArray.length;
+ // XXX need to repaint the lines, tree won't do this
+ treeBoxObject.invalidateRange(this.lastChild(), index);
+ // append the wrapped object
+ itemArray.push(new optionObject(child, 1));
+ treeBoxObject.rowCountChanged(index, 1);
+ selectTreeIndex(index, false);
+ },
+ canDestroy: function canDestroy(prompt)
+ {
+ return false;
+ },
+ canMoveDown: function canMoveDown()
+ {
+ return false;
+ },
+ // helper methods
+ // Find the index of the next immediate child of the select
+ nextChild: function nextChild(index)
+ {
+ while (++index < itemArray.length && itemArray[index].level > 1);
+ return index;
+ },
+ // Find the index of the last immediate child of the select
+ lastChild: function lastChild()
+ {
+ var index = itemArray.length;
+ while (itemArray[--index].level > 1);
+ return index;
+ }
+ }
+ // Start with the <select> wrapper
+ itemArray = [gDialog];
+
+ // We modify the actual option and optgroup elements so clone them first
+ for (var child = selectElement.firstChild; child; child = child.nextSibling)
+ {
+ if (child.tagName == "OPTION")
+ itemArray.push(new optionObject(child.cloneNode(true), 1));
+ else if (child.tagName == "OPTGROUP")
+ {
+ itemArray.push(new optgroupObject(child.cloneNode(false)));
+ for (var grandchild = child.firstChild; grandchild; grandchild = grandchild.nextSibling)
+ if (grandchild.tagName == "OPTION")
+ itemArray.push(new optionObject(grandchild.cloneNode(true), 2));
+ }
+ }
+
+ UpdateSelectMultiple();
+
+ // Define a custom view for the tree
+ treeBoxObject = gDialog.tree.treeBoxObject;
+ treeBoxObject.view = {
+ QueryInterface : function QueryInterface(aIID)
+ {
+ if (aIID.equals(Components.interfaces.nsITreeView) ||
+ aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+ aIID.equals(Components.interfaces.nsISupports))
+ return this;
+
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ },
+ // useful for debugging
+ get wrappedJSObject() { return this; },
+ get rowCount() { return itemArray.length; },
+ get selection() { return treeSelection; },
+ set selection(selection) { return treeSelection = selection; },
+ getRowProperties: function getRowProperties(index, column, prop) { },
+ // could have used a wrapper for this
+ getCellProperties: function getCellProperties(index, column, prop)
+ {
+ if (column.id == "SelectSelCol" && !itemArray[index].container)
+ prop.AppendElement(checkedAtoms[itemArray[index].element.hasAttribute("selected")]);
+ },
+ getColumnProperties: function getColumnProperties(column, prop) { },
+ // get info from wrapper
+ isContainer: function isContainer(index) { return itemArray[index].container; },
+ isContainerOpen: function isContainerOpen(index) { return true; },
+ isContainerEmpty: function isContainerEmpty(index) { return true; },
+ isSeparator: function isSeparator(index) { return false; },
+ isSorted: function isSorted() { return false; },
+ // d&d not implemented yet!
+ canDrop: function canDrop(index, orientation) { return false; },
+ drop: function drop(index, orientation) { alert('drop:' + index + ',' + orientation); },
+ // same as the global helper
+ getParentIndex: getParentIndex,
+ // tree needs to know when to paint lines
+ hasNextSibling: function hasNextSibling(index, after)
+ {
+ if (!index)
+ return false;
+ var level = itemArray[index].level;
+ while (++after < itemArray.length)
+ switch (level - itemArray[after].level)
+ {
+ case 1: return false;
+ case 0: return true;
+ }
+ return false;
+ },
+ getLevel: function getLevel(index) { return itemArray[index].level; },
+ getImageSrc: function getImageSrc(index, column) { },
+ getProgressMode : function getProgressMode(index,column) { },
+ getCellValue: function getCellValue(index, column) { },
+ getCellText: function getCellText(index, column) { return itemArray[index].getCellText(column); },
+ setTree: function setTree(tree) { this.tree = tree; },
+ toggleOpenState: function toggleOpenState(index) { },
+ cycleHeader: function cycleHeader(col) { },
+ selectionChanged: function selectionChanged()
+ {
+ // Save current values and update buttons and deck
+ if (currentItem)
+ currentItem.onBlur();
+ var currentIndex = treeSelection.currentIndex;
+ currentItem = itemArray[currentIndex];
+ gDialog.removeButton.disabled = !currentItem.canDestroy();
+ gDialog.previousButton.disabled = currentIndex < 2;
+ gDialog.nextButton.disabled = !currentItem.canMoveDown();
+ // For Advanced Edit
+ globalElement = currentItem.element;
+ currentItem.onFocus();
+ },
+ cycleCell: function cycleCell(index, column) { itemArray[index].cycleCell(index); },
+ isEditable: function isEditable(index, column) { return false; },
+ isSelectable: function isSelectable(index, column) { return false; },
+ performAction: function performAction(action) { },
+ performActionOnCell: function performActionOnCell(action, index, column) { }
+ };
+ treeSelection.select(0);
+ currentItem = gDialog;
+ //onNameInput();
+
+ SetTextboxFocus(gDialog.selectName);
+
+ SetWindowLocation();
+}
+
+// Called from Advanced Edit
+function InitDialog()
+{
+ currentItem.onFocus();
+}
+
+// Called from Advanced Edit
+function ValidateData()
+{
+ currentItem.onBlur();
+ return true;
+}
+
+function onAccept()
+{
+ // All values are valid - copy to actual element in doc or
+ // element created to insert
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ // Coalesce into one undo transaction
+ editor.beginTransaction();
+
+ try
+ {
+ editor.cloneAttributes(selectElement, gDialog.element);
+
+ if (insertNew)
+ // 'true' means delete the selection before inserting
+ editor.insertElementAtSelection(selectElement, true);
+
+ editor.setShouldTxnSetSelection(false);
+
+ while (selectElement.lastChild)
+ editor.deleteNode(selectElement.lastChild);
+
+ var offset = 0;
+ for (var i = 1; i < itemArray.length; i++)
+ if (itemArray[i].level > 1)
+ selectElement.lastChild.appendChild(itemArray[i].element);
+ else
+ editor.insertNode(itemArray[i].element, selectElement, offset++, true);
+
+ editor.setShouldTxnSetSelection(true);
+ }
+ finally
+ {
+ editor.endTransaction();
+ }
+
+ SaveWindowLocation();
+
+ return true;
+}
+
+// Button actions
+function AddOption()
+{
+ currentItem.appendOption(GetCurrentEditor().createElementWithDefaults("option"), treeSelection.currentIndex);
+ SetTextboxFocus(gDialog.optionText);
+}
+
+function AddOptGroup()
+{
+ var optgroupElement = GetCurrentEditor().createElementWithDefaults("optgroup");
+ var index = itemArray.length;
+ // XXX need to repaint the lines, tree won't do this
+ treeBoxObject.invalidateRange(gDialog.lastChild(), index);
+ // append the wrapped object
+ itemArray.push(new optgroupObject(optgroupElement));
+ treeBoxObject.rowCountChanged(index, 1);
+ selectTreeIndex(index, false);
+ SetTextboxFocus(gDialog.optgroupLabel);
+}
+
+function RemoveElement()
+{
+ if (currentItem.canDestroy(true))
+ {
+ // Only removing empty option groups for now
+ var index = treeSelection.currentIndex;
+ var level = itemArray[index].level;
+ // Perform necessary cleanup and remove the wrapper
+ itemArray[index].destroy();
+ itemArray.splice(index, 1);
+ --index;
+ // XXX need to repaint the lines, tree won't do this
+ if (level == 1) {
+ var last = gDialog.lastChild();
+ if (index > last)
+ treeBoxObject.invalidateRange(last, index);
+ }
+ selectTreeIndex(index, true);
+ treeBoxObject.rowCountChanged(++index, -1);
+ }
+}
+
+// Event handler
+function onTreeKeyUp(event)
+{
+ if (event.keyCode == event.DOM_VK_SPACE)
+ currentItem.cycleCell();
+}
+
+function onNameInput()
+{
+ var disabled = !gDialog.selectName.value;
+ if (gDialog.accept.disabled != disabled)
+ gDialog.accept.disabled = disabled;
+ gDialog.element.setAttribute("name", gDialog.selectName.value);
+ // repaint the tree
+ var primaryCol = treeBoxObject.getPrimaryColumn();
+ treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
+}
+
+function onLabelInput()
+{
+ currentItem.element.setAttribute("label", gDialog.optgroupLabel.value);
+ // repaint the tree
+ var primaryCol = treeBoxObject.getPrimaryColumn();
+ treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
+}
+
+function onTextInput()
+{
+ currentItem.element.text = gDialog.optionText.value;
+ // repaint the tree
+ if (hasValue) {
+ var primaryCol = treeBoxObject.getPrimaryColumn();
+ treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
+ }
+ else
+ {
+ gDialog.optionValue.value = gDialog.optionText.value;
+ treeBoxObject.invalidateRow(treeSelection.currentIndex);
+ }
+}
+
+function onValueInput()
+{
+ gDialog.optionHasValue.checked = hasValue = true;
+ oldValue = gDialog.optionValue.value;
+ currentItem.element.setAttribute("value", oldValue);
+ // repaint the tree
+ var column = treeBoxObject.columns["SelectValCol"];
+ treeBoxObject.invalidateCell(treeSelection.currentIndex, column);
+}
+
+function onHasValueClick()
+{
+ hasValue = gDialog.optionHasValue.checked;
+ if (hasValue)
+ {
+ gDialog.optionValue.value = oldValue;
+ currentItem.element.setAttribute("value", oldValue);
+ }
+ else
+ {
+ oldValue = gDialog.optionValue.value;
+ gDialog.optionValue.value = gDialog.optionText.value;
+ currentItem.element.removeAttribute("value");
+ }
+ // repaint the tree
+ var column = treeBoxObject.columns["SelectValCol"];
+ treeBoxObject.invalidateCell(treeSelection.currentIndex, column);
+}
+
+function onSelectMultipleClick()
+{
+ // Recalculate the unique selected option if we need it and have lost it
+ if (!gDialog.selectMultiple.checked && selectedOptionCount == 1 && !selectedOption)
+ for (var i = 1; !(selectedOption = itemArray[i].element).hasAttribute("selected"); i++);
+}
+
+function selectTreeIndex(index, focus)
+{
+ treeSelection.select(index);
+ treeBoxObject.ensureRowIsVisible(index);
+ if (focus)
+ gDialog.tree.focus();
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSelectProps.xul
@@ -0,0 +1,161 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Selection List Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSelectProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdSelectProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <!-- Setting rows="7" on tree isn't working, equalsize vbox sets tree height. -->
+ <vbox equalsize="always">
+ <tree id="SelectTree" onselect="treeBoxObject.view.selectionChanged();" onkeyup="onTreeKeyUp(event);">
+ <treecols id="SelectCols">
+ <treecol id="SelectTextCol" flex="3" label="&TextHeader.label;" primary="true"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="SelectValCol" flex="2" label="&ValueHeader.label;"/>
+ <treecol id="SelectSelCol" label="&SelectedHeader.label;" cycler="true"/>
+ </treecols>
+
+ <treechildren id="SelectTreeChildren"/>
+ </tree>
+
+ <hbox flex="1">
+ <deck flex="1" id="SelectDeck" index="0">
+ <groupbox flex="1"><caption label="&Select.label;"/>
+ <grid flex="1"><columns><column flex="1"/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="SelectName" value="&SelectName.label;" accesskey="&SelectName.accesskey;"/>
+ <textbox id="SelectName" flex="1" oninput="onNameInput();"/>
+ </row>
+ <row align="center">
+ <label control="SelectSize" value="&SelectSize.label;" accesskey="&SelectSize.accesskey;"/>
+ <hbox>
+ <textbox id="SelectSize" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="SelectMultiple" flex="1" label="&SelectMultiple.label;" accesskey="&SelectMultiple.accesskey;" oncommand="onSelectMultipleClick();"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="SelectDisabled" flex="1" label="&SelectDisabled.label;" accesskey="&SelectDisabled.accesskey;"/>
+ </row>
+ <row align="center">
+ <label control="SelectTabIndex" value="&SelectTabIndex.label;" accesskey="&SelectTabIndex.accesskey;"/>
+ <hbox>
+ <textbox id="SelectTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <groupbox flex="1"><caption label="&OptGroup.label;"/>
+ <grid flex="1"><columns><column flex="1"/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="OptGroupLabel" value="&OptGroupLabel.label;" accesskey="&OptGroupLabel.accesskey;"/>
+ <textbox id="OptGroupLabel" oninput="onLabelInput();"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="OptGroupDisabled" label="&OptGroupDisabled.label;" accesskey="&OptGroupDisabled.accesskey;"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <groupbox flex="1"><caption label="&Option.label;"/>
+ <grid flex="1"><columns><column flex="1"/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="OptionText" value="&OptionText.label;" accesskey="&OptionText.accesskey;"/>
+ <textbox id="OptionText" oninput="onTextInput();"/>
+ </row>
+ <row align="center">
+ <checkbox id="OptionHasValue" label="&OptionValue.label;" accesskey="&OptionValue.accesskey;" oncommand="onHasValueClick();"/>
+ <textbox id="OptionValue" oninput="onValueInput();"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="OptionSelected" label="&OptionSelected.label;" accesskey="&OptionSelected.accesskey;" oncommand="currentItem.cycleCell();"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="OptionDisabled" label="&OptionDisabled.label;" accesskey="&OptionDisabled.accesskey;"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+ </deck>
+
+ <vbox>
+ <button label="&AddOption.label;" accesskey="&AddOption.accesskey;" oncommand="AddOption();"/>
+ <button label="&AddOptGroup.label;" accesskey="&AddOptGroup.accesskey;" oncommand="AddOptGroup();"/>
+ <button id="RemoveButton" label="&RemoveElement.label;" accesskey="&RemoveElement.accesskey;"
+ oncommand="RemoveElement();" disabled="true"/>
+ <button id="PreviousButton" label="&MoveElementUp.label;" accesskey="&MoveElementUp.accesskey;"
+ oncommand="currentItem.moveUp();" disabled="true" type="row"/>
+ <button id="NextButton" label="&MoveElementDown.label;" accesskey="&MoveElementDown.accesskey;"
+ oncommand="currentItem.moveDown();" disabled="true" type="row"/>
+ <spacer flex="1"/>
+ <button id="AdvancedEditButton"/>
+ </vbox>
+ </hbox>
+ </vbox>
+
+ <separator class="groove"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSnapToGrid.js
@@ -0,0 +1,94 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gPrefs = GetPrefs();
+var gEditor;
+
+// dialog initialization code
+function Startup()
+{
+ gEditor = GetCurrentEditor();
+ if (!gEditor)
+ {
+ window.close();
+ return;
+ }
+
+ gEditor instanceof Components.interfaces.nsIHTMLAbsPosEditor;
+
+ gDialog.enableSnapToGrid = document.getElementById("enableSnapToGrid");
+ gDialog.sizeInput = document.getElementById("size");
+ gDialog.sizeLabel = document.getElementById("sizeLabel");
+ gDialog.unitLabel = document.getElementById("unitLabel");
+
+ // Initialize control values based on existing attributes
+ InitDialog()
+
+ // SET FOCUS TO FIRST CONTROL
+ SetTextboxFocus(gDialog.sizeInput);
+
+ // Resize window
+ window.sizeToContent();
+
+ SetWindowLocation();
+}
+
+// Set dialog widgets with attribute data
+// We get them from globalElement copy so this can be used
+// by AdvancedEdit(), which is shared by all property dialogs
+function InitDialog()
+{
+ gDialog.enableSnapToGrid.checked = gEditor.snapToGridEnabled;
+ toggleSnapToGrid();
+
+ gDialog.sizeInput.value = gEditor.gridSize;
+}
+
+function onAccept()
+{
+ gEditor.snapToGridEnabled = gDialog.enableSnapToGrid.checked;
+ gEditor.gridSize = gDialog.sizeInput.value;
+
+ return true;
+}
+
+function toggleSnapToGrid()
+{
+ SetElementEnabledById("size", gDialog.enableSnapToGrid.checked)
+ SetElementEnabledById("sizeLabel", gDialog.enableSnapToGrid.checked)
+ SetElementEnabledById("unitLabel", gDialog.enableSnapToGrid.checked)
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSnapToGrid.xul
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla.org.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Daniel Glazman (glazman@netscape.com) (Original author)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
+<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSnapToGrid.dtd">
+
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <!--- Element-specific methods -->
+ <script type="application/x-javascript" src="chrome://editor/content/EdSnapToGrid.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <checkbox id="enableSnapToGrid"
+ label="&enableSnapToGrid.label;"
+ accesskey="&enableSnapToGrid.accessKey;"
+ oncommand="toggleSnapToGrid();"/>
+
+ <spacer class="spacer"/>
+
+ <grid>
+ <columns><column/><column/><column /></columns>
+ <rows>
+ <row align="center">
+ <label value="&sizeEditField.label;"
+ id="sizeLabel"
+ control="size"
+ accesskey="&sizeEditField.accessKey;"/>
+ <textbox class="narrow" id="size" oninput="forceInteger('size')"/>
+ <label id="unitLabel"
+ value="&pixelsLabel.value;" />
+ </row>
+ </rows>
+ </grid>
+
+ <spacer class="spacer"/>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSpellCheck.js
@@ -0,0 +1,621 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gMisspelledWord;
+var gSpellChecker = null;
+var gAllowSelectWord = true;
+var gPreviousReplaceWord = "";
+var gFirstTime = true;
+var gLastSelectedLang = null;
+var gDictCount = 0;
+
+function Startup()
+{
+ var sendMailMessageMode = false;
+
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ // Get the spellChecker shell
+ gSpellChecker = Components.classes['@mozilla.org/editor/editorspellchecker;1'].createInstance(Components.interfaces.nsIEditorSpellCheck);
+ if (!gSpellChecker)
+ {
+ dump("SpellChecker not found!!!\n");
+ window.close();
+ return;
+ }
+
+ // Start the spell checker module.
+ try {
+ // TxtSrv Filter Contract Id
+ var filterContractId;
+ sendMailMessageMode = window.arguments[0];
+ var skipBlockQuotes = window.arguments[1];
+ var enableSelectionChecking = window.arguments[2];
+
+ if (skipBlockQuotes)
+ filterContractId = "@mozilla.org/editor/txtsrvfiltermail;1";
+ else
+ filterContractId = "@mozilla.org/editor/txtsrvfilter;1";
+
+ gSpellChecker.setFilter(Components.classes[filterContractId].createInstance(Components.interfaces.nsITextServicesFilter));
+ gSpellChecker.InitSpellChecker(editor, enableSelectionChecking);
+
+ }
+ catch(ex) {
+ dump("*** Exception error: InitSpellChecker\n");
+ window.close();
+ return;
+ }
+
+ gDialog.MisspelledWordLabel = document.getElementById("MisspelledWordLabel");
+ gDialog.MisspelledWord = document.getElementById("MisspelledWord");
+ gDialog.ReplaceButton = document.getElementById("Replace");
+ gDialog.IgnoreButton = document.getElementById("Ignore");
+ gDialog.StopButton = document.getElementById("Stop");
+ gDialog.CloseButton = document.getElementById("Close");
+ gDialog.ReplaceWordInput = document.getElementById("ReplaceWordInput");
+ gDialog.SuggestedList = document.getElementById("SuggestedList");
+ gDialog.LanguageMenulist = document.getElementById("LanguageMenulist");
+
+ // Fill in the language menulist and sync it up
+ // with the spellchecker's current language.
+
+ var curLang;
+
+ try {
+ curLang = gSpellChecker.GetCurrentDictionary();
+ } catch(ex) {
+ curLang = "";
+ }
+
+ InitLanguageMenu(curLang);
+
+ // Get the first misspelled word and setup all UI
+ NextWord();
+
+ // When startup param is true, setup different UI when spell checking
+ // just before sending mail message
+ if (sendMailMessageMode)
+ {
+ // If no misspelled words found, simply close dialog and send message
+ if (!gMisspelledWord)
+ {
+ onClose();
+ return;
+ }
+
+ // Hide "Close" button and use "Send" instead
+ gDialog.CloseButton.hidden = true;
+ gDialog.CloseButton = document.getElementById("Send");
+ gDialog.CloseButton.hidden = false;
+ }
+ else
+ {
+ // Normal spell checking - hide the "Stop" button
+ // (Note that this button is the "Cancel" button for
+ // Esc keybinding and related window close actions)
+ gDialog.StopButton.hidden = true;
+ }
+
+ // Clear flag that determines message when
+ // no misspelled word is found
+ // (different message when used for the first time)
+ gFirstTime = false;
+}
+
+function InitLanguageMenu(aCurLang)
+{
+
+ var o1 = {};
+ var o2 = {};
+
+ // Get the list of dictionaries from
+ // the spellchecker.
+
+ try
+ {
+ gSpellChecker.GetDictionaryList(o1, o2);
+ }
+ catch(ex)
+ {
+ dump("Failed to get DictionaryList!\n");
+ return;
+ }
+
+ var dictList = o1.value;
+ var count = o2.value;
+
+ // If we're not just starting up and dictionary count
+ // hasn't changed then no need to update the menu.
+ if (gDictCount == count)
+ return;
+
+ // Store current dictionary count.
+ gDictCount = count;
+
+ // Load the string bundles that will help us map
+ // RFC 1766 strings to UI strings.
+
+ // Load the language string bundle.
+ var languageBundle = document.getElementById("languageBundle");
+ var regionBundle = null;
+ // If we have a language string bundle, load the region string bundle.
+ if (languageBundle)
+ regionBundle = document.getElementById("regionBundle");
+
+ var menuStr2;
+ var isoStrArray;
+ var langId;
+ var langLabel;
+ var i;
+
+ for (i = 0; i < count; i++)
+ {
+ try
+ {
+ langId = dictList[i];
+ isoStrArray = dictList[i].split("-");
+
+ if (languageBundle && isoStrArray[0])
+ langLabel = languageBundle.getString(isoStrArray[0].toLowerCase());
+
+ if (regionBundle && langLabel && isoStrArray.length > 1 && isoStrArray[1])
+ {
+ menuStr2 = regionBundle.getString(isoStrArray[1].toLowerCase());
+ if (menuStr2)
+ langLabel += "/" + menuStr2;
+ }
+
+ if (langLabel && isoStrArray.length > 2 && isoStrArray[2])
+ langLabel += " (" + isoStrArray[2] + ")";
+
+ if (!langLabel)
+ langLabel = langId;
+ }
+ catch (ex)
+ {
+ // getString throws an exception when a key is not found in the
+ // bundle. In that case, just use the original dictList string.
+ langLabel = langId;
+ }
+ dictList[i] = [langLabel, langId];
+ }
+
+ // sort by locale-aware collation
+ dictList.sort(
+ function compareFn(a, b)
+ {
+ return a[0].localeCompare(b[0]);
+ }
+ );
+
+ // Remove any languages from the list.
+ var languageMenuPopup = gDialog.LanguageMenulist.firstChild;
+ while (languageMenuPopup.firstChild.localName != "menuseparator")
+ languageMenuPopup.removeChild(languageMenuPopup.firstChild);
+
+ var defaultItem = null;
+
+ for (i = 0; i < count; i++)
+ {
+ var item = gDialog.LanguageMenulist.insertItemAt(i, dictList[i][0], dictList[i][1]);
+ if (aCurLang && dictList[i][1] == aCurLang)
+ defaultItem = item;
+ }
+
+ // Now make sure the correct item in the menu list is selected.
+ if (defaultItem)
+ {
+ gDialog.LanguageMenulist.selectedItem = defaultItem;
+ gLastSelectedLang = defaultItem;
+ }
+}
+
+function DoEnabling()
+{
+ if (!gMisspelledWord)
+ {
+ // No more misspelled words
+ gDialog.MisspelledWord.setAttribute("value",GetString( gFirstTime ? "NoMisspelledWord" : "CheckSpellingDone"));
+
+ gDialog.ReplaceButton.removeAttribute("default");
+ gDialog.IgnoreButton.removeAttribute("default");
+
+ gDialog.CloseButton.setAttribute("default","true");
+ // Shouldn't have to do this if "default" is true?
+ gDialog.CloseButton.focus();
+
+ SetElementEnabledById("MisspelledWordLabel", false);
+ SetElementEnabledById("ReplaceWordLabel", false);
+ SetElementEnabledById("ReplaceWordInput", false);
+ SetElementEnabledById("CheckWord", false);
+ SetElementEnabledById("SuggestedListLabel", false);
+ SetElementEnabledById("SuggestedList", false);
+ SetElementEnabledById("Ignore", false);
+ SetElementEnabledById("IgnoreAll", false);
+ SetElementEnabledById("Replace", false);
+ SetElementEnabledById("ReplaceAll", false);
+ SetElementEnabledById("AddToDictionary", false);
+ } else {
+ SetElementEnabledById("MisspelledWordLabel", true);
+ SetElementEnabledById("ReplaceWordLabel", true);
+ SetElementEnabledById("ReplaceWordInput", true);
+ SetElementEnabledById("CheckWord", true);
+ SetElementEnabledById("SuggestedListLabel", true);
+ SetElementEnabledById("SuggestedList", true);
+ SetElementEnabledById("Ignore", true);
+ SetElementEnabledById("IgnoreAll", true);
+ SetElementEnabledById("AddToDictionary", true);
+
+ gDialog.CloseButton.removeAttribute("default");
+ SetReplaceEnable();
+ }
+}
+
+function NextWord()
+{
+ gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
+ SetWidgetsForMisspelledWord();
+}
+
+function SetWidgetsForMisspelledWord()
+{
+ gDialog.MisspelledWord.setAttribute("value", TruncateStringAtWordEnd(gMisspelledWord, 30, true));
+
+
+ // Initial replace word is misspelled word
+ gDialog.ReplaceWordInput.value = gMisspelledWord;
+ gPreviousReplaceWord = gMisspelledWord;
+
+ // This sets gDialog.ReplaceWordInput to first suggested word in list
+ FillSuggestedList(gMisspelledWord);
+
+ DoEnabling();
+
+ if (gMisspelledWord)
+ SetTextboxFocus(gDialog.ReplaceWordInput);
+}
+
+function CheckWord()
+{
+ var word = gDialog.ReplaceWordInput.value;
+ if (word)
+ {
+ if (gSpellChecker.CheckCurrentWord(word))
+ {
+ FillSuggestedList(word);
+ SetReplaceEnable();
+ }
+ else
+ {
+ ClearListbox(gDialog.SuggestedList);
+ var item = gDialog.SuggestedList.appendItem(GetString("CorrectSpelling"), "");
+ if (item) item.setAttribute("disabled", "true");
+ // Suppress being able to select the message text
+ gAllowSelectWord = false;
+ }
+ }
+}
+
+function SelectSuggestedWord()
+{
+ if (gAllowSelectWord)
+ {
+ var selectedItem
+ if (gDialog.SuggestedList.selectedItem)
+ {
+ var selValue = gDialog.SuggestedList.selectedItem.getAttribute("label");
+ gDialog.ReplaceWordInput.value = selValue;
+ gPreviousReplaceWord = selValue;
+ }
+ else
+ {
+ gDialog.ReplaceWordInput.value = gPreviousReplaceWord;
+ }
+ SetReplaceEnable();
+ }
+}
+
+function ChangeReplaceWord()
+{
+ // Calling this triggers SelectSuggestedWord(),
+ // so temporarily suppress the effect of that
+ var saveAllow = gAllowSelectWord;
+ gAllowSelectWord = false;
+
+ // Select matching word in list
+ var newIndex = -1;
+ var newSelectedItem;
+ var replaceWord = TrimString(gDialog.ReplaceWordInput.value);
+ if (replaceWord)
+ {
+ for (var i = 0; i < gDialog.SuggestedList.getRowCount(); i++)
+ {
+ var item = gDialog.SuggestedList.getItemAtIndex(i);
+ if (item.getAttribute("label") == replaceWord)
+ {
+ newSelectedItem = item;
+ break;
+ }
+ }
+ }
+ gDialog.SuggestedList.selectedItem = newSelectedItem;
+
+ gAllowSelectWord = saveAllow;
+
+ // Remember the new word
+ gPreviousReplaceWord = gDialog.ReplaceWordInput.value;
+
+ SetReplaceEnable();
+}
+
+function Ignore()
+{
+ NextWord();
+}
+
+function IgnoreAll()
+{
+ if (gMisspelledWord) {
+ gSpellChecker.IgnoreWordAllOccurrences(gMisspelledWord);
+ }
+ NextWord();
+}
+
+function Replace(newWord)
+{
+ if (!newWord)
+ return;
+
+ if (gMisspelledWord && gMisspelledWord != newWord)
+ {
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+ try {
+ gSpellChecker.ReplaceWord(gMisspelledWord, newWord, false);
+ } catch (e) {}
+ editor.endTransaction();
+ }
+ NextWord();
+}
+
+function ReplaceAll()
+{
+ var newWord = gDialog.ReplaceWordInput.value;
+ if (gMisspelledWord && gMisspelledWord != newWord)
+ {
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+ try {
+ gSpellChecker.ReplaceWord(gMisspelledWord, newWord, true);
+ } catch (e) {}
+ editor.endTransaction();
+ }
+ NextWord();
+}
+
+function AddToDictionary()
+{
+ if (gMisspelledWord) {
+ gSpellChecker.AddWordToDictionary(gMisspelledWord);
+ }
+ NextWord();
+}
+
+function EditDictionary()
+{
+ window.openDialog("chrome://editor/content/EdDictionary.xul", "_blank", "chrome,close,titlebar,modal", "", gMisspelledWord);
+}
+
+function SelectLanguage()
+{
+ try {
+ var item = gDialog.LanguageMenulist.selectedItem;
+ if (item.value != "more-cmd") {
+ gSpellChecker.SetCurrentDictionary(item.value);
+ gLastSelectedLang = item;
+ }
+ else {
+ var dictionaryUrl = getDictionaryURL();
+
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ uri = ioService.newURI(dictionaryUrl, null, null);
+ var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
+ .getService(Components.interfaces.nsIExternalProtocolService);
+ if (protocolSvc.isExposedProtocol(uri.scheme))
+ opener.openDialog(getBrowserURL(), "_blank", "all,dialog=no", dictionaryUrl);
+ else
+ protocolSvc.loadUrl(uri);
+
+ if (gLastSelectedLang)
+ gDialog.LanguageMenulist.selectedItem = gLastSelectedLang;
+ }
+ } catch (ex) {
+ dump(ex);
+ }
+}
+
+function getDictionaryURL()
+{
+ var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
+ .getService(Components.interfaces.nsIURLFormatter);
+
+ return formatter.formatURLPref("spellchecker.dictionaries.download.url");
+}
+
+function Recheck()
+{
+ //TODO: Should we bother to add a "Recheck" method to interface?
+ try {
+ var curLang = gSpellChecker.GetCurrentDictionary();
+ gSpellChecker.UninitSpellChecker();
+ gSpellChecker.InitSpellChecker(GetCurrentEditor(), false);
+ gSpellChecker.SetCurrentDictionary(curLang);
+ gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
+ SetWidgetsForMisspelledWord();
+ } catch(ex) {
+ dump(ex);
+ }
+}
+
+function FillSuggestedList(misspelledWord)
+{
+ var list = gDialog.SuggestedList;
+
+ // Clear the current contents of the list
+ gAllowSelectWord = false;
+ ClearListbox(list);
+ var item;
+
+ if (misspelledWord.length > 0)
+ {
+ // Get suggested words until an empty string is returned
+ var count = 0;
+ var firstWord = 0;
+ do {
+ var word = gSpellChecker.GetSuggestedWord();
+ if (count==0)
+ firstWord = word;
+ if (word.length > 0)
+ {
+ list.appendItem(word, "");
+ count++;
+ }
+ } while (word.length > 0);
+
+ if (count == 0)
+ {
+ // No suggestions - show a message but don't let user select it
+ item = list.appendItem(GetString("NoSuggestedWords"));
+ if (item) item.setAttribute("disabled", "true");
+ gAllowSelectWord = false;
+ } else {
+ gAllowSelectWord = true;
+ // Initialize with first suggested list by selecting it
+ gDialog.SuggestedList.selectedIndex = 0;
+ }
+ }
+ else
+ {
+ item = list.appendItem("", "");
+ if (item)
+ item.setAttribute("disabled", "true");
+ }
+}
+
+function SetReplaceEnable()
+{
+ // Enable "Change..." buttons only if new word is different than misspelled
+ var newWord = gDialog.ReplaceWordInput.value;
+ var enable = newWord.length > 0 && newWord != gMisspelledWord;
+ SetElementEnabledById("Replace", enable);
+ SetElementEnabledById("ReplaceAll", enable);
+ if (enable)
+ {
+ gDialog.ReplaceButton.setAttribute("default","true");
+ gDialog.IgnoreButton.removeAttribute("default");
+ }
+ else
+ {
+ gDialog.IgnoreButton.setAttribute("default","true");
+ gDialog.ReplaceButton.removeAttribute("default");
+ }
+}
+
+function doDefault()
+{
+ if (gDialog.ReplaceButton.getAttribute("default") == "true")
+ Replace(gDialog.ReplaceWordInput.value);
+ else if (gDialog.IgnoreButton.getAttribute("default") == "true")
+ Ignore();
+ else if (gDialog.CloseButton.getAttribute("default") == "true")
+ onClose();
+
+ return false;
+}
+
+function ExitSpellChecker()
+{
+ if (gSpellChecker)
+ {
+ try
+ {
+ var curLang = gSpellChecker.GetCurrentDictionary();
+ gSpellChecker.UninitSpellChecker();
+ if ("@mozilla.org/spellchecker;1" in Components.classes) {
+ var spellChecker = Components.classes["@mozilla.org/spellchecker/engine;1"]
+ .getService(Components.interfaces.mozISpellCheckingEngine);
+ spellChecker.dictionary = curLang;
+ }
+ // now check the document over again with the new dictionary
+ // if we have an inline spellchecker
+ if (("InlineSpellCheckerUI" in window.opener) &&
+ window.opener.InlineSpellCheckerUI.enabled)
+ window.opener.InlineSpellCheckerUI.mInlineSpellChecker.spellCheckRange(null);
+ }
+ finally
+ {
+ gSpellChecker = null;
+ }
+ }
+}
+
+function CancelSpellCheck()
+{
+ ExitSpellChecker();
+
+ // Signal to calling window that we canceled
+ window.opener.cancelSendMessage = true;
+ return true;
+}
+
+function onClose()
+{
+ ExitSpellChecker();
+
+ window.opener.cancelSendMessage = false;
+ window.close();
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdSpellCheck.xul
@@ -0,0 +1,147 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSpellCheck.dtd">
+
+<!-- dialog containing a control requiring initial setup -->
+<dialog buttons="cancel" title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ persist="screenX screenY"
+ onload = "Startup()"
+ ondialogaccept="return doDefault();"
+ ondialogcancel="return CancelSpellCheck();">
+
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://communicator/content/utilityOverlay.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdSpellCheck.js"/>
+
+ <broadcaster id="args" value=""/>
+
+ <stringbundle id="languageBundle" src="chrome://global/locale/languageNames.properties"/>
+ <stringbundle id="regionBundle" src="chrome://global/locale/regionNames.properties"/>
+
+ <grid>
+ <columns>
+ <column class="spell-check"/>
+ <column class="spell-check" flex="1"/>
+ <column class="spell-check"/>
+ </columns>
+ <rows>
+ <row align="center">
+ <label id="MisspelledWordLabel" value="&misspelledWord.label;"/>
+ <label class="bold" id="MisspelledWord"/>
+ <button class="spell-check" label="&recheckButton.label;" oncommand="Recheck();"
+ accesskey="&recheckButton.accessKey;"/>
+ </row>
+ <row align="center">
+ <label id="ReplaceWordLabel" value="&wordEditField.label;"
+ control="ReplaceWordInput"
+ accesskey="&wordEditField.accessKey;"/>
+ <textbox id="ReplaceWordInput" oninput="ChangeReplaceWord()" flex="1"/>
+ <button id="CheckWord" oncommand="CheckWord()" label="&checkwordButton.label;"
+ accesskey="&checkwordButton.accessKey;"/>
+ </row>
+ </rows>
+ </grid>
+ <label id="SuggestedListLabel" value="&suggestions.label;"
+ control="SuggestedList"
+ accesskey="&suggestions.accessKey;"/>
+ <grid>
+ <columns><column/><column/></columns>
+ <rows>
+ <row flex="1">
+ <!-- BUG! setting class="MinWidth20em" on tree doesn't work (width=0) -->
+ <listbox rows="6" id="SuggestedList" onselect="SelectSuggestedWord()"
+ ondblclick="if (gAllowSelectWord) Replace(event.target.getAttribute('label'));"/>
+ <vbox>
+ <grid flex="1">
+ <columns><column class="spell-check" flex="1"/><column class="spell-check" flex="1"/></columns>
+ <rows>
+ <row>
+ <button id="Replace" label="&replaceButton.label;"
+ oncommand="Replace(gDialog.ReplaceWordInput.value);"
+ accesskey="&replaceButton.accessKey;"/>
+ <button id="Ignore" oncommand="Ignore();" label="&ignoreButton.label;"
+ accesskey="&ignoreButton.accessKey;"/>
+ </row>
+ <row>
+ <button id="ReplaceAll" oncommand="ReplaceAll();" label="&replaceAllButton.label;"
+ accesskey="&replaceAllButton.accessKey;"/>
+ <button id="IgnoreAll" oncommand="IgnoreAll();" label="&ignoreAllButton.label;"
+ accesskey="&ignoreAllButton.accessKey;"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer flex="1"/>
+ <label value="&userDictionary.label;"/>
+ <hbox flex="1" align="start">
+ <button class="spell-check" id="AddToDictionary" oncommand="AddToDictionary()" label="&addToUserDictionaryButton.label;"
+ accesskey="&addToUserDictionaryButton.accessKey;"/>
+ <button class="spell-check" id="EditDictionary" oncommand="EditDictionary()" label="&editUserDictionaryButton.label;"
+ accesskey="&editUserDictionaryButton.accessKey;"/>
+ </hbox>
+ </vbox>
+ </row>
+ <label value ="&languagePopup.label;"
+ control="LanguageMenulist"
+ accesskey="&languagePopup.accessKey;"/>
+ <row>
+ <menulist id="LanguageMenulist" oncommand="SelectLanguage()">
+ <menupopup onpopupshowing="InitLanguageMenu(gDialog.LanguageMenulist.selectedItem.value);">
+ <!-- dynamic content populated by JS -->
+ <menuseparator/>
+ <menuitem value="more-cmd" label="&moreDictionaries.label;"/>
+ </menupopup>
+ </menulist>
+ <hbox flex="1">
+ <button class="spell-check" dlgtype="cancel" id="Stop" label="&stopButton.label;" oncommand="CancelSpellCheck();"
+ accesskey="&stopButton.accessKey;"/>
+ <spacer flex="1"/>
+ <button class="spell-check" id="Close" label="&closeButton.label;" oncommand="onClose();"
+ accesskey="&closeButton.accessKey;"/>
+ <button class="spell-check" id="Send" label="&sendButton.label;" oncommand="onClose();"
+ accesskey="&sendButton.accessKey;" hidden="true"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdTableProps.js
@@ -0,0 +1,1314 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben Goodger
+ * Charles Manske (cmanske@netscape.com)
+ * Neil Rashbrook (neil@parkwaycc.co.uk)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//Cancel() is in EdDialogCommon.js
+var gTableElement;
+var gCellElement;
+var gTableCaptionElement;
+var globalCellElement;
+var globalTableElement
+var gValidateTab;
+const defHAlign = "left";
+const centerStr = "center"; //Index=1
+const rightStr = "right"; // 2
+const justifyStr = "justify"; // 3
+const charStr = "char"; // 4
+const defVAlign = "middle";
+const topStr = "top";
+const bottomStr = "bottom";
+const bgcolor = "bgcolor";
+var gTableColor;
+var gCellColor;
+
+const cssBackgroundColorStr = "background-color";
+
+var gRowCount = 1;
+var gColCount = 1;
+var gLastRowIndex;
+var gLastColIndex;
+var gNewRowCount;
+var gNewColCount;
+var gCurRowIndex;
+var gCurColIndex;
+var gCurColSpan;
+var gSelectedCellsType = 1;
+const SELECT_CELL = 1;
+const SELECT_ROW = 2;
+const SELECT_COLUMN = 3;
+const RESET_SELECTION = 0;
+var gCellData = { value:null, startRowIndex:0, startColIndex:0, rowSpan:0, colSpan:0,
+ actualRowSpan:0, actualColSpan:0, isSelected:false
+ };
+var gAdvancedEditUsed;
+var gAlignWasChar = false;
+
+/*
+From C++:
+ 0 TABLESELECTION_TABLE
+ 1 TABLESELECTION_CELL There are 1 or more cells selected
+ but complete rows or columns are not selected
+ 2 TABLESELECTION_ROW All cells are in 1 or more rows
+ and in each row, all cells selected
+ Note: This is the value if all rows (thus all cells) are selected
+ 3 TABLESELECTION_COLUMN All cells are in 1 or more columns
+*/
+
+var gSelectedCellCount = 0;
+var gApplyUsed = false;
+var gSelection;
+var gCellDataChanged = false;
+var gCanDelete = false;
+var gPrefs = GetPrefs();
+var gUseCSS = true;
+var gActiveEditor;
+
+// dialog initialization code
+function Startup()
+{
+ gActiveEditor = GetCurrentTableEditor();
+ if (!gActiveEditor)
+ {
+ window.close();
+ return;
+ }
+
+ try {
+ gSelection = gActiveEditor.selection;
+ } catch (e) {}
+ if (!gSelection) return;
+
+ // Get dialog widgets - Table Panel
+ gDialog.TableRowsInput = document.getElementById("TableRowsInput");
+ gDialog.TableColumnsInput = document.getElementById("TableColumnsInput");
+ gDialog.TableWidthInput = document.getElementById("TableWidthInput");
+ gDialog.TableWidthUnits = document.getElementById("TableWidthUnits");
+ gDialog.TableHeightInput = document.getElementById("TableHeightInput");
+ gDialog.TableHeightUnits = document.getElementById("TableHeightUnits");
+ try {
+ if (!gPrefs.getBoolPref("editor.use_css") || (gActiveEditor.flags & 1))
+ {
+ gUseCSS = false;
+ var tableHeightLabel = document.getElementById("TableHeightLabel");
+ tableHeightLabel.parentNode.removeChild(tableHeightLabel);
+ gDialog.TableHeightInput.parentNode.removeChild(gDialog.TableHeightInput);
+ gDialog.TableHeightUnits.parentNode.removeChild(gDialog.TableHeightUnits);
+ }
+ } catch (e) {}
+ gDialog.BorderWidthInput = document.getElementById("BorderWidthInput");
+ gDialog.SpacingInput = document.getElementById("SpacingInput");
+ gDialog.PaddingInput = document.getElementById("PaddingInput");
+ gDialog.TableAlignList = document.getElementById("TableAlignList");
+ gDialog.TableCaptionList = document.getElementById("TableCaptionList");
+ gDialog.TableInheritColor = document.getElementById("TableInheritColor");
+ gDialog.TabBox = document.getElementById("TabBox");
+
+ // Cell Panel
+ gDialog.SelectionList = document.getElementById("SelectionList");
+ gDialog.PreviousButton = document.getElementById("PreviousButton");
+ gDialog.NextButton = document.getElementById("NextButton");
+ // Currently, we always apply changes and load new attributes when changing selection
+ // (Let's keep this for possible future use)
+ //gDialog.ApplyBeforeMove = document.getElementById("ApplyBeforeMove");
+ //gDialog.KeepCurrentData = document.getElementById("KeepCurrentData");
+
+ gDialog.CellHeightInput = document.getElementById("CellHeightInput");
+ gDialog.CellHeightUnits = document.getElementById("CellHeightUnits");
+ gDialog.CellWidthInput = document.getElementById("CellWidthInput");
+ gDialog.CellWidthUnits = document.getElementById("CellWidthUnits");
+ gDialog.CellHAlignList = document.getElementById("CellHAlignList");
+ gDialog.CellVAlignList = document.getElementById("CellVAlignList");
+ gDialog.CellInheritColor = document.getElementById("CellInheritColor");
+ gDialog.CellStyleList = document.getElementById("CellStyleList");
+ gDialog.TextWrapList = document.getElementById("TextWrapList");
+
+ // In cell panel, user must tell us which attributes to apply via checkboxes,
+ // else we would apply values from one cell to ALL in selection
+ // and that's probably not what they expect!
+ gDialog.CellHeightCheckbox = document.getElementById("CellHeightCheckbox");
+ gDialog.CellWidthCheckbox = document.getElementById("CellWidthCheckbox");
+ gDialog.CellHAlignCheckbox = document.getElementById("CellHAlignCheckbox");
+ gDialog.CellVAlignCheckbox = document.getElementById("CellVAlignCheckbox");
+ gDialog.CellStyleCheckbox = document.getElementById("CellStyleCheckbox");
+ gDialog.TextWrapCheckbox = document.getElementById("TextWrapCheckbox");
+ gDialog.CellColorCheckbox = document.getElementById("CellColorCheckbox");
+ gDialog.TableTab = document.getElementById("TableTab");
+ gDialog.CellTab = document.getElementById("CellTab");
+ gDialog.AdvancedEditCell = document.getElementById("AdvancedEditButton2");
+ // Save "normal" tooltip message for Advanced Edit button
+ gDialog.AdvancedEditCellToolTipText = gDialog.AdvancedEditCell.getAttribute("tooltiptext");
+
+ try {
+ gTableElement = gActiveEditor.getElementOrParentByTagName("table", null);
+ } catch (e) {}
+ if(!gTableElement)
+ {
+ dump("Failed to get table element!\n");
+ window.close();
+ return;
+ }
+ globalTableElement = gTableElement.cloneNode(false);
+
+ var tagNameObj = { value: "" };
+ var countObj = { value : 0 };
+ var tableOrCellElement;
+ try {
+ tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
+ } catch (e) {}
+
+ if (tagNameObj.value == "td")
+ {
+ // We are in a cell
+ gSelectedCellCount = countObj.value;
+ gCellElement = tableOrCellElement;
+ globalCellElement = gCellElement.cloneNode(false);
+
+ // Tells us whether cell, row, or column is selected
+ try {
+ gSelectedCellsType = gActiveEditor.getSelectedCellsType(gTableElement);
+ } catch (e) {}
+
+ // Ignore types except Cell, Row, and Column
+ if (gSelectedCellsType < SELECT_CELL || gSelectedCellsType > SELECT_COLUMN)
+ gSelectedCellsType = SELECT_CELL;
+
+ // Be sure at least 1 cell is selected.
+ // (If the count is 0, then we were inside the cell.)
+ if (gSelectedCellCount == 0)
+ DoCellSelection();
+
+ // Get location in the cell map
+ var rowIndexObj = { value: 0 };
+ var colIndexObj = { value: 0 };
+ try {
+ gActiveEditor.getCellIndexes(gCellElement, rowIndexObj, colIndexObj);
+ } catch (e) {}
+ gCurRowIndex = rowIndexObj.value;
+ gCurColIndex = colIndexObj.value;
+
+ // We save the current colspan to quickly
+ // move selection from from cell to cell
+ if (GetCellData(gCurRowIndex, gCurColIndex))
+ gCurColSpan = gCellData.colSpan;
+
+ // Starting TabPanel name is passed in
+ if (window.arguments[1] == "CellPanel")
+ gDialog.TabBox.selectedTab = gDialog.CellTab;
+ }
+
+ if (gDialog.TabBox.selectedTab == gDialog.TableTab)
+ {
+ // We may call this with table selected, but no cell,
+ // so disable the Cell Properties tab
+ if(!gCellElement)
+ {
+ // XXX: Disabling of tabs is currently broken, so for
+ // now we'll just remove the tab completely.
+ //gDialog.CellTab.disabled = true;
+ gDialog.CellTab.parentNode.removeChild(gDialog.CellTab);
+ }
+ }
+
+ // Note: we must use gTableElement, not globalTableElement for these,
+ // thus we should not put this in InitDialog.
+ // Instead, monitor desired counts with separate globals
+ var rowCountObj = { value: 0 };
+ var colCountObj = { value: 0 };
+ try {
+ gActiveEditor.getTableSize(gTableElement, rowCountObj, colCountObj);
+ } catch (e) {}
+
+ gRowCount = rowCountObj.value;
+ gLastRowIndex = gRowCount-1;
+ gColCount = colCountObj.value;
+ gLastColIndex = gColCount-1;
+
+
+ // Set appropriate icons and enable state for the Previous/Next buttons
+ SetSelectionButtons();
+
+ // If only one cell in table, disable change-selection widgets
+ if (gRowCount == 1 && gColCount == 1)
+ gDialog.SelectionList.setAttribute("disabled", "true");
+
+ // User can change these via textboxes
+ gNewRowCount = gRowCount;
+ gNewColCount = gColCount;
+
+ // This flag is used to control whether set check state
+ // on "set attribute" checkboxes
+ // (Advanced Edit dialog use calls InitDialog when done)
+ gAdvancedEditUsed = false;
+ InitDialog();
+ gAdvancedEditUsed = true;
+
+ // If first initializing, we really aren't changing anything
+ gCellDataChanged = false;
+
+ if (gDialog.TabBox.selectedTab == gDialog.CellTab)
+ setTimeout("gDialog.SelectionList.focus()", 0);
+ else
+ SetTextboxFocus(gDialog.TableRowsInput);
+
+ SetWindowLocation();
+}
+
+
+function InitDialog()
+{
+ // Get Table attributes
+ gDialog.TableRowsInput.value = gRowCount;
+ gDialog.TableColumnsInput.value = gColCount;
+ gDialog.TableWidthInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "width", "TableWidthUnits", gPercent);
+ if (gUseCSS) {
+ gDialog.TableHeightInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "height",
+ "TableHeightUnits", gPercent);
+ }
+ gDialog.BorderWidthInput.value = globalTableElement.border;
+ gDialog.SpacingInput.value = globalTableElement.cellSpacing;
+ gDialog.PaddingInput.value = globalTableElement.cellPadding;
+
+ var marginLeft = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-left");
+ var marginRight = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-right");
+ var halign = marginLeft.toLowerCase() + " " + marginRight.toLowerCase();
+ if (halign == "center center" || halign == "auto auto")
+ gDialog.TableAlignList.value = "center";
+ else if (halign == "right right" || halign == "auto 0px")
+ gDialog.TableAlignList.value = "right";
+ else // Default = left
+ gDialog.TableAlignList.value = "left";
+
+ // Be sure to get caption from table in doc, not the copied "globalTableElement"
+ gTableCaptionElement = gTableElement.caption;
+ if (gTableCaptionElement)
+ {
+ var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side");
+ if (align != "bottom" && align != "left" && align != "right")
+ align = "top";
+ gDialog.TableCaptionList.value = align;
+ }
+
+ gTableColor = GetHTMLOrCSSStyleValue(globalTableElement, bgcolor, cssBackgroundColorStr);
+ gTableColor = ConvertRGBColorIntoHEXColor(gTableColor);
+ SetColor("tableBackgroundCW", gTableColor);
+
+ InitCellPanel();
+}
+
+function InitCellPanel()
+{
+ // Get cell attributes
+ if (globalCellElement)
+ {
+ // This assumes order of items is Cell, Row, Column
+ gDialog.SelectionList.value = gSelectedCellsType;
+
+ var previousValue = gDialog.CellHeightInput.value;
+ gDialog.CellHeightInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "height", "CellHeightUnits", gPixel);
+ gDialog.CellHeightCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellHeightInput.value;
+
+ previousValue= gDialog.CellWidthInput.value;
+ gDialog.CellWidthInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "width", "CellWidthUnits", gPixel);
+ gDialog.CellWidthCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellWidthInput.value;
+
+ var previousIndex = gDialog.CellVAlignList.selectedIndex;
+ var valign = GetHTMLOrCSSStyleValue(globalCellElement, "valign", "vertical-align").toLowerCase();
+ if (valign == topStr || valign == bottomStr)
+ gDialog.CellVAlignList.value = valign;
+ else // Default = middle
+ gDialog.CellVAlignList.value = defVAlign;
+
+ gDialog.CellVAlignCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellVAlignList.selectedIndex;
+
+ previousIndex = gDialog.CellHAlignList.selectedIndex;
+
+ gAlignWasChar = false;
+
+ var halign = GetHTMLOrCSSStyleValue(globalCellElement, "align", "text-align").toLowerCase();
+ switch (halign)
+ {
+ case centerStr:
+ case rightStr:
+ case justifyStr:
+ gDialog.CellHAlignList.value = halign;
+ break;
+ case charStr:
+ // We don't support UI for this because layout doesn't work: bug 2212.
+ // Remember that's what they had so we don't change it
+ // unless they change the alignment by using the menulist
+ gAlignWasChar = true;
+ // Fall through to use show default alignment in menu
+ default:
+ // Default depends on cell type (TH is "center", TD is "left")
+ gDialog.CellHAlignList.value =
+ (globalCellElement.nodeName.toLowerCase() == "th") ? "center" : "left";
+ break;
+ }
+
+ gDialog.CellHAlignCheckbox.checked = gAdvancedEditUsed &&
+ previousIndex != gDialog.CellHAlignList.selectedIndex;
+
+ previousIndex = gDialog.CellStyleList.selectedIndex;
+ gDialog.CellStyleList.value = globalCellElement.nodeName.toLowerCase();
+ gDialog.CellStyleCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellStyleList.selectedIndex;
+
+ previousIndex = gDialog.TextWrapList.selectedIndex;
+ if (GetHTMLOrCSSStyleValue(globalCellElement, "nowrap", "white-space") == "nowrap")
+ gDialog.TextWrapList.value = "nowrap";
+ else
+ gDialog.TextWrapList.value = "wrap";
+ gDialog.TextWrapCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.TextWrapList.selectedIndex;
+
+ previousValue = gCellColor;
+ gCellColor = GetHTMLOrCSSStyleValue(globalCellElement, bgcolor, cssBackgroundColorStr);
+ gCellColor = ConvertRGBColorIntoHEXColor(gCellColor);
+ SetColor("cellBackgroundCW", gCellColor);
+ gDialog.CellColorCheckbox.checked = gAdvancedEditUsed && previousValue != gCellColor;
+
+ // We want to set this true in case changes came
+ // from Advanced Edit dialog session (must assume something changed)
+ gCellDataChanged = true;
+ }
+}
+
+function GetCellData(rowIndex, colIndex)
+{
+ // Get actual rowspan and colspan
+ var startRowIndexObj = { value: 0 };
+ var startColIndexObj = { value: 0 };
+ var rowSpanObj = { value: 0 };
+ var colSpanObj = { value: 0 };
+ var actualRowSpanObj = { value: 0 };
+ var actualColSpanObj = { value: 0 };
+ var isSelectedObj = { value: false };
+
+ try {
+ gActiveEditor.getCellDataAt(gTableElement, rowIndex, colIndex,
+ gCellData,
+ startRowIndexObj, startColIndexObj,
+ rowSpanObj, colSpanObj,
+ actualRowSpanObj, actualColSpanObj, isSelectedObj);
+ // We didn't find a cell
+ if (!gCellData.value) return false;
+ }
+ catch(ex) {
+ return false;
+ }
+
+ gCellData.startRowIndex = startRowIndexObj.value;
+ gCellData.startColIndex = startColIndexObj.value;
+ gCellData.rowSpan = rowSpanObj.value;
+ gCellData.colSpan = colSpanObj.value;
+ gCellData.actualRowSpan = actualRowSpanObj.value;
+ gCellData.actualColSpan = actualColSpanObj.value;
+ gCellData.isSelected = isSelectedObj.value;
+ return true;
+}
+
+function SelectCellHAlign()
+{
+ SetCheckbox("CellHAlignCheckbox");
+ // Once user changes the alignment,
+ // we lose their original "CharAt" alignment"
+ gAlignWasChar = false;
+}
+
+function GetColorAndUpdate(ColorWellID)
+{
+ var colorWell = document.getElementById(ColorWellID);
+ if (!colorWell) return;
+
+ var colorObj = { Type:"", TableColor:0, CellColor:0, NoDefault:false, Cancel:false, BackgroundColor:0 };
+
+ switch( ColorWellID )
+ {
+ case "tableBackgroundCW":
+ colorObj.Type = "Table";
+ colorObj.TableColor = gTableColor;
+ break;
+ case "cellBackgroundCW":
+ colorObj.Type = "Cell";
+ colorObj.CellColor = gCellColor;
+ break;
+ }
+ window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
+
+ // User canceled the dialog
+ if (colorObj.Cancel)
+ return;
+
+ switch( ColorWellID )
+ {
+ case "tableBackgroundCW":
+ gTableColor = colorObj.BackgroundColor;
+ SetColor(ColorWellID, gTableColor);
+ break;
+ case "cellBackgroundCW":
+ gCellColor = colorObj.BackgroundColor;
+ SetColor(ColorWellID, gCellColor);
+ SetCheckbox('CellColorCheckbox');
+ break;
+ }
+}
+
+function SetColor(ColorWellID, color)
+{
+ // Save the color
+ if (ColorWellID == "cellBackgroundCW")
+ {
+ if (color)
+ {
+ try {
+ gActiveEditor.setAttributeOrEquivalent(globalCellElement, bgcolor,
+ color, true);
+ } catch(e) {}
+ gDialog.CellInheritColor.collapsed = true;
+ }
+ else
+ {
+ try {
+ gActiveEditor.removeAttributeOrEquivalent(globalCellElement, bgcolor, true);
+ } catch(e) {}
+ // Reveal addition message explaining "default" color
+ gDialog.CellInheritColor.collapsed = false;
+ }
+ }
+ else
+ {
+ if (color)
+ {
+ try {
+ gActiveEditor.setAttributeOrEquivalent(globalTableElement, bgcolor,
+ color, true);
+ } catch(e) {}
+ gDialog.TableInheritColor.collapsed = true;
+ }
+ else
+ {
+ try {
+ gActiveEditor.removeAttributeOrEquivalent(globalTableElement, bgcolor, true);
+ } catch(e) {}
+ gDialog.TableInheritColor.collapsed = false;
+ }
+ SetCheckbox('CellColorCheckbox');
+ }
+
+ setColorWell(ColorWellID, color);
+}
+
+function ChangeSelectionToFirstCell()
+{
+ if (!GetCellData(0,0))
+ {
+ dump("Can't find first cell in table!\n");
+ return;
+ }
+ gCellElement = gCellData.value;
+ globalCellElement = gCellElement;
+
+ gCurRowIndex = 0;
+ gCurColIndex = 0;
+ ChangeSelection(RESET_SELECTION);
+}
+
+function ChangeSelection(newType)
+{
+ newType = Number(newType);
+
+ if (gSelectedCellsType == newType)
+ return;
+
+ if (newType == RESET_SELECTION)
+ // Restore selection to existing focus cell
+ gSelection.collapse(gCellElement,0);
+ else
+ gSelectedCellsType = newType;
+
+ // Keep the same focus gCellElement, just change the type
+ DoCellSelection();
+ SetSelectionButtons();
+
+ // Note: globalCellElement should still be a clone of gCellElement
+}
+
+function MoveSelection(forward)
+{
+ var newRowIndex = gCurRowIndex;
+ var newColIndex = gCurColIndex;
+ var focusCell;
+ var inRow = false;
+
+ if (gSelectedCellsType == SELECT_ROW)
+ {
+ newRowIndex += (forward ? 1 : -1);
+
+ // Wrap around if before first or after last row
+ if (newRowIndex < 0)
+ newRowIndex = gLastRowIndex;
+ else if (newRowIndex > gLastRowIndex)
+ newRowIndex = 0;
+ inRow = true;
+
+ // Use first cell in row for focus cell
+ newColIndex = 0;
+ }
+ else
+ {
+ // Cell or column:
+ if (!forward)
+ newColIndex--;
+
+ if (gSelectedCellsType == SELECT_CELL)
+ {
+ // Skip to next cell
+ if (forward)
+ newColIndex += gCurColSpan;
+ }
+ else // SELECT_COLUMN
+ {
+ // Use first cell in column for focus cell
+ newRowIndex = 0;
+
+ // Don't skip by colspan,
+ // but find first cell in next cellmap column
+ if (forward)
+ newColIndex++;
+ }
+
+ if (newColIndex < 0)
+ {
+ // Request is before the first cell in column
+
+ // Wrap to last cell in column
+ newColIndex = gLastColIndex;
+
+ if (gSelectedCellsType == SELECT_CELL)
+ {
+ // If moving by cell, also wrap to previous...
+ if (newRowIndex > 0)
+ newRowIndex -= 1;
+ else
+ // ...or the last row
+ newRowIndex = gLastRowIndex;
+
+ inRow = true;
+ }
+ }
+ else if (newColIndex > gLastColIndex)
+ {
+ // Request is after the last cell in column
+
+ // Wrap to first cell in column
+ newColIndex = 0;
+
+ if (gSelectedCellsType == SELECT_CELL)
+ {
+ // If moving by cell, also wrap to next...
+ if (newRowIndex < gLastRowIndex)
+ newRowIndex++;
+ else
+ // ...or the first row
+ newRowIndex = 0;
+
+ inRow = true;
+ }
+ }
+ }
+
+ // Get the cell at the new location
+ do {
+ if (!GetCellData(newRowIndex, newColIndex))
+ {
+ dump("MoveSelection: CELL NOT FOUND\n");
+ return;
+ }
+ if (inRow)
+ {
+ if (gCellData.startRowIndex == newRowIndex)
+ break;
+ else
+ // Cell spans from a row above, look for the next cell in row
+ newRowIndex += gCellData.actualRowSpan;
+ }
+ else
+ {
+ if (gCellData.startColIndex == newColIndex)
+ break;
+ else
+ // Cell spans from a Col above, look for the next cell in column
+ newColIndex += gCellData.actualColSpan;
+ }
+ }
+ while(true);
+
+ // Save data for current selection before changing
+ if (gCellDataChanged) // && gDialog.ApplyBeforeMove.checked)
+ {
+ if (!ValidateCellData())
+ return;
+
+ gActiveEditor.beginTransaction();
+ // Apply changes to all selected cells
+ ApplyCellAttributes();
+ gActiveEditor.endTransaction();
+
+ SetCloseButton();
+ }
+
+ // Set cell and other data for new selection
+ gCellElement = gCellData.value;
+
+ // Save globals for new current cell
+ gCurRowIndex = gCellData.startRowIndex;
+ gCurColIndex = gCellData.startColIndex;
+ gCurColSpan = gCellData.actualColSpan;
+
+ // Copy for new global cell
+ globalCellElement = gCellElement.cloneNode(false);
+
+ // Change the selection
+ DoCellSelection();
+
+ // Scroll page so new selection is visible
+ // Using SELECTION_ANCHOR_REGION makes the upper-left corner of first selected cell
+ // the point to bring into view.
+ try {
+ var selectionController = gActiveEditor.selectionController;
+ selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION, true);
+ } catch (e) {}
+
+ // Reinitialize dialog using new cell
+// if (!gDialog.KeepCurrentData.checked)
+ // Setting this false unchecks all "set attributes" checkboxes
+ gAdvancedEditUsed = false;
+ InitCellPanel();
+ gAdvancedEditUsed = true;
+}
+
+
+function DoCellSelection()
+{
+ // Collapse selection into to the focus cell
+ // so editor uses that as start cell
+ gSelection.collapse(gCellElement, 0);
+
+ var tagNameObj = { value: "" };
+ var countObj = { value: 0 };
+ try {
+ switch (gSelectedCellsType)
+ {
+ case SELECT_CELL:
+ gActiveEditor.selectTableCell();
+ break
+ case SELECT_ROW:
+ gActiveEditor.selectTableRow();
+ break;
+ default:
+ gActiveEditor.selectTableColumn();
+ break;
+ }
+ // Get number of cells selected
+ var tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
+ } catch (e) {}
+
+ if (tagNameObj.value == "td")
+ gSelectedCellCount = countObj.value;
+ else
+ gSelectedCellCount = 0;
+
+ // Currently, we can only allow advanced editing on ONE cell element at a time
+ // else we ignore CSS, JS, and HTML attributes not already in dialog
+ SetElementEnabled(gDialog.AdvancedEditCell, gSelectedCellCount == 1);
+
+ gDialog.AdvancedEditCell.setAttribute("tooltiptext",
+ gSelectedCellCount > 1 ? GetString("AdvancedEditForCellMsg") :
+ gDialog.AdvancedEditCellToolTipText);
+}
+
+function SetSelectionButtons()
+{
+ if (gSelectedCellsType == SELECT_ROW)
+ {
+ // Trigger CSS to set images of up and down arrows
+ gDialog.PreviousButton.setAttribute("type","row");
+ gDialog.NextButton.setAttribute("type","row");
+ }
+ else
+ {
+ // or images of left and right arrows
+ gDialog.PreviousButton.setAttribute("type","col");
+ gDialog.NextButton.setAttribute("type","col");
+ }
+ DisableSelectionButtons((gSelectedCellsType == SELECT_ROW && gRowCount == 1) ||
+ (gSelectedCellsType == SELECT_COLUMN && gColCount == 1) ||
+ (gRowCount == 1 && gColCount == 1));
+}
+
+function DisableSelectionButtons( disable )
+{
+ gDialog.PreviousButton.setAttribute("disabled", disable ? "true" : "false");
+ gDialog.NextButton.setAttribute("disabled", disable ? "true" : "false");
+}
+
+function SwitchToValidatePanel()
+{
+ if (gDialog.TabBox.selectedTab != gValidateTab)
+ gDialog.TabBox.selectedTab = gValidateTab;
+}
+
+function SetAlign(listID, defaultValue, element, attName)
+{
+ var value = document.getElementById(listID).value;
+ if (value == defaultValue)
+ {
+ try {
+ gActiveEditor.removeAttributeOrEquivalent(element, attName, true);
+ } catch(e) {}
+ }
+ else
+ {
+ try {
+ gActiveEditor.setAttributeOrEquivalent(element, attName, value, true);
+ } catch(e) {}
+ }
+}
+
+function ValidateTableData()
+{
+ gValidateTab = gDialog.TableTab;
+ gNewRowCount = Number(ValidateNumber(gDialog.TableRowsInput, null, 1, gMaxRows, null, true, true));
+ if (gValidationError) return false;
+
+ gNewColCount = Number(ValidateNumber(gDialog.TableColumnsInput, null, 1, gMaxColumns, null, true, true));
+ if (gValidationError) return false;
+
+ // If user is deleting any cells, get confirmation
+ // (This is a global to the dialog and we ask only once per dialog session)
+ if ( !gCanDelete &&
+ (gNewRowCount < gRowCount ||
+ gNewColCount < gColCount) )
+ {
+ if (ConfirmWithTitle(GetString("DeleteTableTitle"),
+ GetString("DeleteTableMsg"),
+ GetString("DeleteCells")) )
+ {
+ gCanDelete = true;
+ }
+ else
+ {
+ SetTextboxFocus(gNewRowCount < gRowCount ? gDialog.TableRowsInput : gDialog.TableColumnsInput);
+ return false;
+ }
+ }
+
+ ValidateNumber(gDialog.TableWidthInput, gDialog.TableWidthUnits,
+ 1, gMaxTableSize, globalTableElement, "width");
+ if (gValidationError) return false;
+
+ if (gUseCSS) {
+ ValidateNumber(gDialog.TableHeightInput, gDialog.TableHeightUnits,
+ 1, gMaxTableSize, globalTableElement, "height");
+ if (gValidationError) return false;
+ }
+
+ var border = ValidateNumber(gDialog.BorderWidthInput, null, 0, gMaxPixels, globalTableElement, "border");
+ // TODO: Deal with "BORDER" without value issue
+ if (gValidationError) return false;
+
+ ValidateNumber(gDialog.SpacingInput, null, 0, gMaxPixels, globalTableElement, "cellspacing");
+ if (gValidationError) return false;
+
+ ValidateNumber(gDialog.PaddingInput, null, 0, gMaxPixels, globalTableElement, "cellpadding");
+ if (gValidationError) return false;
+
+ SetAlign("TableAlignList", defHAlign, globalTableElement, "align");
+
+ // Color is set on globalCellElement immediately
+ return true;
+}
+
+function ValidateCellData()
+{
+
+ gValidateTab = gDialog.CellTab;
+
+ if (gDialog.CellHeightCheckbox.checked)
+ {
+ ValidateNumber(gDialog.CellHeightInput, gDialog.CellHeightUnits,
+ 1, gMaxTableSize, globalCellElement, "height");
+ if (gValidationError) return false;
+ }
+
+ if (gDialog.CellWidthCheckbox.checked)
+ {
+ ValidateNumber(gDialog.CellWidthInput, gDialog.CellWidthUnits,
+ 1, gMaxTableSize, globalCellElement, "width");
+ if (gValidationError) return false;
+ }
+
+ if (gDialog.CellHAlignCheckbox.checked)
+ {
+ var hAlign = gDialog.CellHAlignList.value;
+
+ // Horizontal alignment is complicated by "char" type
+ // We don't change current values if user didn't edit alignment
+ if (!gAlignWasChar)
+ {
+ globalCellElement.removeAttribute(charStr);
+
+ // Always set "align" attribute,
+ // so the default "left" is effective in a cell
+ // when parent row has align set.
+ globalCellElement.setAttribute("align", hAlign);
+ }
+ }
+
+ if (gDialog.CellVAlignCheckbox.checked)
+ {
+ // Always set valign (no default in 2nd param) so
+ // the default "middle" is effective in a cell
+ // when parent row has valign set.
+ SetAlign("CellVAlignList", "", globalCellElement, "valign");
+ }
+
+ if (gDialog.TextWrapCheckbox.checked)
+ {
+ if (gDialog.TextWrapList.value == "nowrap")
+ try {
+ gActiveEditor.setAttributeOrEquivalent(globalCellElement, "nowrap",
+ "nowrap", true);
+ } catch(e) {}
+ else
+ try {
+ gActiveEditor.removeAttributeOrEquivalent(globalCellElement, "nowrap", true);
+ } catch(e) {}
+ }
+
+ return true;
+}
+
+function ValidateData()
+{
+ var result;
+
+ // Validate current panel first
+ if (gDialog.TabBox.selectedTab == gDialog.TableTab)
+ {
+ result = ValidateTableData();
+ if (result)
+ result = ValidateCellData();
+ } else {
+ result = ValidateCellData();
+ if (result)
+ result = ValidateTableData();
+ }
+ if(!result) return false;
+
+ // Set global element for AdvancedEdit
+ if(gDialog.TabBox.selectedTab == gDialog.TableTab)
+ globalElement = globalTableElement;
+ else
+ globalElement = globalCellElement;
+
+ return true;
+}
+
+function ChangeCellTextbox(textboxID)
+{
+ // Filter input for just integers
+ forceInteger(textboxID);
+
+ if (gDialog.TabBox.selectedTab == gDialog.CellTab)
+ gCellDataChanged = true;
+}
+
+// Call this when a textbox or menulist is changed
+// so the checkbox is automatically set
+function SetCheckbox(checkboxID)
+{
+ if (checkboxID && checkboxID.length > 0)
+ {
+ // Set associated checkbox
+ document.getElementById(checkboxID).checked = true;
+ }
+ gCellDataChanged = true;
+}
+
+function ChangeIntTextbox(textboxID, checkboxID)
+{
+ // Filter input for just integers
+ forceInteger(textboxID);
+
+ // Set associated checkbox
+ SetCheckbox(checkboxID);
+}
+
+function CloneAttribute(destElement, srcElement, attr)
+{
+ var value = srcElement.getAttribute(attr);
+ // Use editor methods since we are always
+ // modifying a table in the document and
+ // we need transaction system for undo
+ try {
+ if (!value || value.length == 0)
+ gActiveEditor.removeAttributeOrEquivalent(destElement, attr, false);
+ else
+ gActiveEditor.setAttributeOrEquivalent(destElement, attr, value, false);
+ } catch(e) {}
+}
+
+function ApplyTableAttributes()
+{
+ var newAlign = gDialog.TableCaptionList.value;
+ if (!newAlign) newAlign = "";
+
+ if (gTableCaptionElement)
+ {
+ // Get current alignment
+ var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side").toLowerCase();
+ // This is the default
+ if (!align) align = "top";
+
+ if (newAlign == "")
+ {
+ // Remove existing caption
+ try {
+ gActiveEditor.deleteNode(gTableCaptionElement);
+ } catch(e) {}
+ gTableCaptionElement = null;
+ }
+ else if(newAlign != align)
+ {
+ try {
+ if (newAlign == "top") // This is default, so don't explicitly set it
+ gActiveEditor.removeAttributeOrEquivalent(gTableCaptionElement, "align", false);
+ else
+ gActiveEditor.setAttributeOrEquivalent(gTableCaptionElement, "align", newAlign, false);
+ } catch(e) {}
+ }
+ }
+ else if (newAlign != "")
+ {
+ // Create and insert a caption:
+ try {
+ gTableCaptionElement = gActiveEditor.createElementWithDefaults("caption");
+ } catch (e) {}
+ if (gTableCaptionElement)
+ {
+ if (newAlign != "top")
+ gTableCaptionElement.setAttribute("align", newAlign);
+
+ // Insert it into the table - caption is always inserted as first child
+ try {
+ gActiveEditor.insertNode(gTableCaptionElement, gTableElement, 0);
+ } catch(e) {}
+
+ // Put selecton back where it was
+ ChangeSelection(RESET_SELECTION);
+ }
+ }
+
+ var countDelta;
+ var foundCell;
+ var i;
+
+ if (gNewRowCount != gRowCount)
+ {
+ countDelta = gNewRowCount - gRowCount;
+ if (gNewRowCount > gRowCount)
+ {
+ // Append new rows
+ // Find first cell in last row
+ if(GetCellData(gLastRowIndex, 0))
+ {
+ try {
+ // Move selection to the last cell
+ gSelection.collapse(gCellData.value,0);
+ // Insert new rows after it
+ gActiveEditor.insertTableRow(countDelta, true);
+ gRowCount = gNewRowCount;
+ gLastRowIndex = gRowCount - 1;
+ // Put selecton back where it was
+ ChangeSelection(RESET_SELECTION);
+ }
+ catch(ex) {
+ dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
+ }
+ }
+ }
+ else
+ {
+ // Delete rows
+ if (gCanDelete)
+ {
+ // Find first cell starting in first row we delete
+ var firstDeleteRow = gRowCount + countDelta;
+ foundCell = false;
+ for ( i = 0; i <= gLastColIndex; i++)
+ {
+ if (!GetCellData(firstDeleteRow, i))
+ break; // We failed to find a cell
+
+ if (gCellData.startRowIndex == firstDeleteRow)
+ {
+ foundCell = true;
+ break;
+ }
+ };
+ if (foundCell)
+ {
+ try {
+ // Move selection to the cell we found
+ gSelection.collapse(gCellData.value, 0);
+ gActiveEditor.deleteTableRow(-countDelta);
+ gRowCount = gNewRowCount;
+ gLastRowIndex = gRowCount - 1;
+ if (gCurRowIndex > gLastRowIndex)
+ // We are deleting our selection
+ // move it to start of table
+ ChangeSelectionToFirstCell()
+ else
+ // Put selecton back where it was
+ ChangeSelection(RESET_SELECTION);
+ }
+ catch(ex) {
+ dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
+ }
+ }
+ }
+ }
+ }
+
+ if (gNewColCount != gColCount)
+ {
+ countDelta = gNewColCount - gColCount;
+
+ if (gNewColCount > gColCount)
+ {
+ // Append new columns
+ // Find last cell in first column
+ if(GetCellData(0, gLastColIndex))
+ {
+ try {
+ // Move selection to the last cell
+ gSelection.collapse(gCellData.value,0);
+ gActiveEditor.insertTableColumn(countDelta, true);
+ gColCount = gNewColCount;
+ gLastColIndex = gColCount-1;
+ // Restore selection
+ ChangeSelection(RESET_SELECTION);
+ }
+ catch(ex) {
+ dump("FAILED TO FIND FIRST CELL IN LAST COLUMN\n");
+ }
+ }
+ }
+ else
+ {
+ // Delete columns
+ if (gCanDelete)
+ {
+ var firstDeleteCol = gColCount + countDelta;
+ foundCell = false;
+ for ( i = 0; i <= gLastRowIndex; i++)
+ {
+ // Find first cell starting in first column we delete
+ if (!GetCellData(i, firstDeleteCol))
+ break; // We failed to find a cell
+
+ if (gCellData.startColIndex == firstDeleteCol)
+ {
+ foundCell = true;
+ break;
+ }
+ };
+ if (foundCell)
+ {
+ try {
+ // Move selection to the cell we found
+ gSelection.collapse(gCellData.value, 0);
+ gActiveEditor.deleteTableColumn(-countDelta);
+ gColCount = gNewColCount;
+ gLastColIndex = gColCount-1;
+ if (gCurColIndex > gLastColIndex)
+ ChangeSelectionToFirstCell()
+ else
+ ChangeSelection(RESET_SELECTION);
+ }
+ catch(ex) {
+ dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
+ }
+ }
+ }
+ }
+ }
+
+ // Clone all remaining attributes to pick up
+ // anything changed by Advanced Edit Dialog
+ try {
+ gActiveEditor.cloneAttributes(gTableElement, globalTableElement);
+ } catch(e) {}
+}
+
+function ApplyCellAttributes()
+{
+ var rangeObj = { value: null };
+ var selectedCell;
+ try {
+ selectedCell = gActiveEditor.getFirstSelectedCell(rangeObj);
+ } catch(e) {}
+
+ if (!selectedCell)
+ return;
+
+ if (gSelectedCellCount == 1)
+ {
+ // When only one cell is selected, simply clone entire element,
+ // thus CSS and JS from Advanced edit is copied
+ try {
+ gActiveEditor.cloneAttributes(selectedCell, globalCellElement);
+ } catch(e) {}
+
+ if (gDialog.CellStyleCheckbox.checked)
+ {
+ var currentStyleIndex = (selectedCell.nodeName.toLowerCase() == "th") ? 1 : 0;
+ if (gDialog.CellStyleList.selectedIndex != currentStyleIndex)
+ {
+ // Switch cell types
+ // (replaces with new cell and copies attributes and contents)
+ try {
+ selectedCell = gActiveEditor.switchTableCellHeaderType(selectedCell);
+ } catch(e) {}
+ }
+ }
+ }
+ else
+ {
+ // Apply changes to all selected cells
+ //XXX THIS DOESN'T COPY ADVANCED EDIT CHANGES!
+ try {
+ while (selectedCell)
+ {
+ ApplyAttributesToOneCell(selectedCell);
+ selectedCell = gActiveEditor.getNextSelectedCell(rangeObj);
+ }
+ } catch(e) {}
+ }
+ gCellDataChanged = false;
+}
+
+function ApplyAttributesToOneCell(destElement)
+{
+ if (gDialog.CellHeightCheckbox.checked)
+ CloneAttribute(destElement, globalCellElement, "height");
+
+ if (gDialog.CellWidthCheckbox.checked)
+ CloneAttribute(destElement, globalCellElement, "width");
+
+ if (gDialog.CellHAlignCheckbox.checked)
+ {
+ CloneAttribute(destElement, globalCellElement, "align");
+ CloneAttribute(destElement, globalCellElement, charStr);
+ }
+
+ if (gDialog.CellVAlignCheckbox.checked)
+ CloneAttribute(destElement, globalCellElement, "valign");
+
+ if (gDialog.TextWrapCheckbox.checked)
+ CloneAttribute(destElement, globalCellElement, "nowrap");
+
+ if (gDialog.CellStyleCheckbox.checked)
+ {
+ var newStyleIndex = gDialog.CellStyleList.selectedIndex;
+ var currentStyleIndex = (destElement.nodeName.toLowerCase() == "th") ? 1 : 0;
+
+ if (newStyleIndex != currentStyleIndex)
+ {
+ // Switch cell types
+ // (replaces with new cell and copies attributes and contents)
+ try {
+ destElement = gActiveEditor.switchTableCellHeaderType(destElement);
+ } catch(e) {}
+ }
+ }
+
+ if (gDialog.CellColorCheckbox.checked)
+ CloneAttribute(destElement, globalCellElement, "bgcolor");
+}
+
+function SetCloseButton()
+{
+ // Change text on "Cancel" button after Apply is used
+ if (!gApplyUsed)
+ {
+ document.documentElement.setAttribute("buttonlabelcancel",
+ document.documentElement.getAttribute("buttonlabelclose"));
+ gApplyUsed = true;
+ }
+}
+
+function Apply()
+{
+ if (ValidateData())
+ {
+ gActiveEditor.beginTransaction();
+
+ ApplyTableAttributes();
+
+ // We may have just a table, so check for cell element
+ if (globalCellElement)
+ ApplyCellAttributes();
+
+ gActiveEditor.endTransaction();
+
+ SetCloseButton();
+ return true;
+ }
+ return false;
+}
+
+function onAccept()
+{
+ // Do same as Apply and close window if ValidateData succeeded
+ var retVal = Apply();
+ if (retVal)
+ SaveWindowLocation();
+
+ return retVal;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdTableProps.xul
@@ -0,0 +1,288 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Ben Goodger
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorTableProperties.dtd">
+
+<dialog title="&tableWindow.title;"
+ id="tableDlg"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ buttons="accept,extra1,cancel"
+ buttonlabelclose="&closeButton.label;"
+ buttonlabelextra1="&applyButton.label;"
+ buttonaccesskeyextra1="&applyButton.accesskey;"
+ ondialogaccept="return onAccept();"
+ ondialogextra1="return Apply();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdTableProps.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <tabbox id="TabBox">
+ <tabs flex="1">
+ <tab id="TableTab" label="&tableTab.label;"/>
+ <tab id="CellTab" label="&cellTab.label;"/>
+ </tabs>
+ <tabpanels>
+
+ <!-- TABLE PANEL -->
+ <vbox>
+ <groupbox orient="horizontal"><caption label="&size.label;"/>
+ <grid>
+ <columns><column/><column/><column/><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label value="&tableRows.label;" accesskey="&tableRows.accessKey;" control="TableRowsInput"/>
+ <textbox class="narrow" id="TableRowsInput" oninput="forceInteger(this.id);"/>
+ <spring class="bigspacer"/>
+ <label value="&tableHeight.label;" accesskey="&tableHeight.accessKey;"
+ id="TableHeightLabel" control="TableHeightInput"/>
+ <textbox class="narrow" id="TableHeightInput" oninput="forceInteger(this.id);"/>
+ <menulist id="TableHeightUnits"/>
+ </row>
+ <row align="center">
+ <label value="&tableColumns.label;" accesskey="&tableColumns.accessKey;" control="TableColumnsInput"/>
+ <textbox class="narrow" id="TableColumnsInput" oninput="forceInteger(this.id);"/>
+ <spring class="bigspacer"/>
+ <label value="&tableWidth.label;" accesskey="&tableWidth.accessKey;" control="TableWidthInput"/>
+ <textbox class="narrow" id="TableWidthInput" oninput="forceInteger(this.id);"/>
+ <menulist id="TableWidthUnits"/>
+ </row>
+ </rows>
+ <!-- KEEP GRID LAYOUT here since we will be adding back support for table HEIGHT via CSS -->
+ </grid>
+ </groupbox>
+ <groupbox><caption label="&tableBorderSpacing.label;"/>
+ <grid>
+ <columns><column/><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="BorderWidthInput"
+ value="&tableBorderWidth.label;"
+ accesskey="&tableBorderWidth.accessKey;"/>
+ <textbox class="narrow" id="BorderWidthInput" oninput="forceInteger(this.id);"/>
+ <label align="left" value="&pixels.label;"/>
+ </row>
+ <row align="center">
+ <label control="SpacingInput"
+ value="&tableSpacing.label;"
+ accesskey="&tableSpacing.accessKey;"/>
+ <textbox class="narrow" id="SpacingInput" oninput="forceInteger(this.id);"/>
+ <label value="&tablePxBetwCells.label;"/>
+ </row>
+ <row align="center">
+ <label control="PaddingInput"
+ value="&tablePadding.label;"
+ accesskey="&tablePadding.accessKey;"/>
+ <textbox class="narrow" id="PaddingInput" oninput="forceInteger(this.id);"/>
+ <label value="&tablePxBetwBrdrCellContent.label;"/>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+ <!-- Table Alignment and Caption -->
+ <hbox flex="1" align="center">
+ <label control="TableAlignList"
+ value="&tableAlignment.label;"
+ accesskey="&tableAlignment.accessKey;"/>
+ <menulist id="TableAlignList">
+ <menupopup>
+ <menuitem label="&AlignLeft.label;" value="left"/>
+ <menuitem label="&AlignCenter.label;" value="center"/>
+ <menuitem label="&AlignRight.label;" value="right"/>
+ </menupopup>
+ </menulist>
+ <spacer class="spacer"/>
+ <label control="TableCaptionList"
+ value="&tableCaption.label;"
+ accesskey="&tableCaption.accessKey;"/>
+ <menulist id="TableCaptionList">
+ <menupopup>
+ <menuitem label="&tableCaptionNone.label;" value=""/>
+ <menuitem label="&tableCaptionAbove.label;" value="top"/>
+ <menuitem label="&tableCaptionBelow.label;" value="bottom"/>
+ <menuitem label="&tableCaptionLeft.label;" value="left"/>
+ <menuitem label="&tableCaptionRight.label;" value="right"/>
+ </menupopup>
+ </menulist>
+ </hbox>
+ <separator class="groove"/>
+ <hbox align="center">
+ <label value="&backgroundColor.label;"/>
+ <button id="tableBackground" class="color-button" oncommand="GetColorAndUpdate('tableBackgroundCW');">
+ <spacer id="tableBackgroundCW" class="color-well"/>
+ </button>
+ <spacer class="spacer"/>
+ <label id="TableInheritColor" value="&tableInheritColor.label;" collapsed="true"/>
+ </hbox>
+ <separator class="groove"/>
+ <hbox flex="1" align="center">
+ <spacer flex="1"/>
+ <!-- From EdDialogOvlerlay.xul -->
+ <button id="AdvancedEditButton"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox><!-- Table Panel -->
+
+ <!-- CELL PANEL -->
+ <vbox>
+ <groupbox orient="horizontal" align="center">
+ <caption label="&cellSelection.label;"/>
+ <vbox>
+ <menulist id="SelectionList" oncommand="ChangeSelection(event.target.value)" flex="1">
+ <menupopup>
+ <!-- JS code assumes order is Cell, Row, Column -->
+ <menuitem label="&cellSelectCell.label;" value="1"/>
+ <menuitem label="&cellSelectRow.label;" value="2"/>
+ <menuitem label="&cellSelectColumn.label;" value="3"/>
+ </menupopup>
+ </menulist>
+ <hbox flex="1">
+ <button id="PreviousButton" label="&cellSelectPrevious.label;" accesskey="&cellSelectPrevious.accessKey;" oncommand="MoveSelection(0)" flex="1"/>
+ <button id="NextButton" class="align-right" label="&cellSelectNext.label;" accesskey="&cellSelectNext.accessKey;" oncommand="MoveSelection(1)" flex="1"/>
+ </hbox>
+ </vbox>
+ <spacer class="bigspacer"/>
+ <vbox flex="1">
+ <label value="&applyBeforeChange1.label;"/>
+ <label value="&applyBeforeChange2.label;"/>
+ </vbox>
+ </groupbox>
+ <hbox align="center">
+ <!-- cell size groupbox -->
+ <groupbox><caption label="&size.label;"/>
+ <grid>
+ <columns><column/><column/><column flex="1"/></columns>
+ <rows>
+ <row align="center">
+ <checkbox id="CellHeightCheckbox" label="&tableHeight.label;" accesskey="&tableHeight.accessKey;"/>
+ <textbox class="narrow" id="CellHeightInput"
+ oninput="ChangeIntTextbox(this.id,'CellHeightCheckbox');"/>
+ <menulist id="CellHeightUnits" oncommand="SetCheckbox('CellHeightCheckbox');"/>
+ </row>
+ <row align="center">
+ <checkbox id="CellWidthCheckbox" label="&tableWidth.label;" accesskey="&tableWidth.accessKey;"/>
+ <textbox class="narrow" id="CellWidthInput"
+ oninput="ChangeIntTextbox(this.id,'CellWidthCheckbox');"/>
+ <menulist id="CellWidthUnits" oncommand="SetCheckbox('CellWidthCheckbox');"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer class="bigspacer"/>
+ </groupbox>
+ <!-- Alignment -->
+ <groupbox><caption label="&cellContentAlignment.label;"/>
+ <grid>
+ <columns><column/><column flex="1"/><column/></columns>
+ <rows>
+ <row align="center">
+ <checkbox id="CellVAlignCheckbox" label="&cellVertical.label;" accesskey="&cellVertical.accessKey;"/>
+ <menulist id="CellVAlignList" oncommand="SetCheckbox('CellVAlignCheckbox');">
+ <menupopup>
+ <menuitem label="&cellAlignTop.label;" value="top"/>
+ <menuitem label="&cellAlignMiddle.label;" value="middle"/>
+ <menuitem label="&cellAlignBottom.label;" value="bottom"/>
+ </menupopup>
+ </menulist>
+ </row>
+ <row align="center">
+ <checkbox id="CellHAlignCheckbox" label="&cellHorizontal.label;" accesskey="&cellHorizontal.accessKey;"/>
+ <menulist id="CellHAlignList" oncommand="SelectCellHAlign()">
+ <menupopup>
+ <menuitem label="&AlignLeft.label;" value="left"/>
+ <menuitem label="&AlignCenter.label;" value="center"/>
+ <menuitem label="&AlignRight.label;" value="right"/>
+ <menuitem label="&cellAlignJustify.label;" value="justify"/>
+ </menupopup>
+ </menulist>
+ </row>
+ </rows>
+ </grid>
+ </groupbox>
+ </hbox>
+ <spacer class="spacer"/>
+ <hbox align="center">
+ <checkbox id="CellStyleCheckbox" label="&cellStyle.label;" accesskey="&cellStyle.accessKey;"/>
+ <menulist id="CellStyleList" oncommand="SetCheckbox('CellStyleCheckbox');">
+ <menupopup>
+ <menuitem label="&cellNormal.label;" value="td"/>
+ <menuitem label="&cellHeader.label;" value="th"/>
+ </menupopup>
+ </menulist>
+ <spacer class="bigspacer"/>
+ <checkbox id="TextWrapCheckbox" label="&cellTextWrap.label;" accesskey="&cellTextWrap.accessKey;"/>
+ <menulist id="TextWrapList" oncommand="SetCheckbox('TextWrapCheckbox');">
+ <menupopup>
+ <menuitem label="&cellWrap.label;" value="wrap"/>
+ <menuitem label="&cellNoWrap.label;" value="nowrap"/>
+ </menupopup>
+ </menulist>
+ </hbox>
+ <separator class="groove"/>
+ <hbox align="center">
+ <checkbox id="CellColorCheckbox" label="&backgroundColor.label;" accesskey="&backgroundColor.accessKey;"/>
+ <button class="color-button" oncommand="GetColorAndUpdate('cellBackgroundCW');">
+ <spacer id="cellBackgroundCW" class="color-well"/>
+ </button>
+ <spacer class="spacer"/>
+ <label id="CellInheritColor" value="&cellInheritColor.label;" collapsed="true"/>
+ </hbox>
+ <separator class="groove"/>
+ <hbox align="center">
+ <description class="wrap" flex="1" style="width: 1em">&cellUseCheckboxHelp.label;</description>
+ <!-- From EdDialogOvlerlay.xul -->
+ <button id="AdvancedEditButton2"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox><!-- Cell Panel -->
+ </tabpanels>
+ </tabbox>
+ <spacer class="spacer"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdTextAreaProps.js
@@ -0,0 +1,200 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Text Area Properties Dialog.
+ *
+ * The Initial Developer of the Original Code is
+ * Neil Rashbrook.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var insertNew;
+var textareaElement;
+
+// dialog initialization code
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ dump("Failed to get active editor!\n");
+ window.close();
+ return;
+ }
+
+ gDialog = {
+ accept: document.documentElement.getButton("accept"),
+ textareaName: document.getElementById("TextAreaName"),
+ textareaRows: document.getElementById("TextAreaRows"),
+ textareaCols: document.getElementById("TextAreaCols"),
+ textareaWrap: document.getElementById("TextAreaWrap"),
+ textareaReadOnly: document.getElementById("TextAreaReadOnly"),
+ textareaDisabled: document.getElementById("TextAreaDisabled"),
+ textareaTabIndex: document.getElementById("TextAreaTabIndex"),
+ textareaAccessKey: document.getElementById("TextAreaAccessKey"),
+ textareaValue: document.getElementById("TextAreaValue"),
+ MoreSection: document.getElementById("MoreSection"),
+ MoreFewerButton: document.getElementById("MoreFewerButton")
+ };
+
+ // Get a single selected text area element
+ const kTagName = "textarea";
+ try {
+ textareaElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
+
+ if (textareaElement) {
+ // We found an element and don't need to insert one
+ insertNew = false;
+
+ gDialog.textareaValue.value = textareaElement.value;
+ }
+ else
+ {
+ insertNew = true;
+
+ // We don't have an element selected,
+ // so create one with default attributes
+ try {
+ textareaElement = editor.createElementWithDefaults(kTagName);
+ } catch(e) {}
+
+ if (!textareaElement)
+ {
+ dump("Failed to get selected element or create a new one!\n");
+ window.close();
+ return;
+ }
+ else
+ gDialog.textareaValue.value = GetSelectionAsText();
+ }
+
+ // Make a copy to use for AdvancedEdit
+ globalElement = textareaElement.cloneNode(false);
+
+ InitDialog();
+
+ InitMoreFewer();
+
+ SetTextboxFocus(gDialog.textareaName);
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ gDialog.textareaName.value = globalElement.getAttribute("name");
+ gDialog.textareaRows.value = globalElement.getAttribute("rows");
+ gDialog.textareaCols.value = globalElement.getAttribute("cols");
+ gDialog.textareaWrap.value = GetHTMLOrCSSStyleValue(globalElement, "wrap", "white-space");
+ gDialog.textareaReadOnly.checked = globalElement.hasAttribute("readonly");
+ gDialog.textareaDisabled.checked = globalElement.hasAttribute("disabled");
+ gDialog.textareaTabIndex.value = globalElement.getAttribute("tabindex");
+ gDialog.textareaAccessKey.value = globalElement.getAttribute("accesskey");
+ onInput();
+}
+
+function onInput()
+{
+ var disabled = !gDialog.textareaName.value || !gDialog.textareaRows.value || !gDialog.textareaCols.value;
+ if (gDialog.accept.disabled != disabled)
+ gDialog.accept.disabled = disabled;
+}
+
+function ValidateData()
+{
+ var attributes = {
+ name: gDialog.textareaName.value,
+ rows: gDialog.textareaRows.value,
+ cols: gDialog.textareaCols.value,
+ wrap: gDialog.textareaWrap.value,
+ tabindex: gDialog.textareaTabIndex.value,
+ accesskey: gDialog.textareaAccessKey.value
+ };
+ var flags = {
+ readonly: gDialog.textareaReadOnly.checked,
+ disabled: gDialog.textareaDisabled.checked
+ };
+ for (var a in attributes)
+ {
+ if (attributes[a])
+ globalElement.setAttribute(a, attributes[a]);
+ else
+ globalElement.removeAttribute(a);
+ }
+ for (var f in flags)
+ {
+ if (flags[f])
+ globalElement.setAttribute(f, "");
+ else
+ globalElement.removeAttribute(f);
+ }
+ return true;
+}
+
+function onAccept()
+{
+ // All values are valid - copy to actual element in doc or
+ // element created to insert
+ ValidateData();
+
+ var editor = GetCurrentEditor();
+
+ editor.beginTransaction();
+
+ try {
+ editor.cloneAttributes(textareaElement, globalElement);
+
+ if (insertNew)
+ editor.insertElementAtSelection(textareaElement, true);
+
+ // undoably set value
+ var initialText = gDialog.textareaValue.value;
+ if (initialText != textareaElement.value) {
+ editor.setShouldTxnSetSelection(false);
+
+ while (textareaElement.hasChildNodes())
+ editor.deleteNode(textareaElement.lastChild);
+ if (initialText) {
+ var textNode = editor.document.createTextNode(initialText);
+ editor.insertNode(textNode, textareaElement, 0);
+ }
+
+ editor.setShouldTxnSetSelection(true);
+ }
+ } finally {
+ editor.endTransaction();
+ }
+
+ SaveWindowLocation();
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EdTextAreaProps.xul
@@ -0,0 +1,135 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Text Area Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorTextAreaProperties.dtd">
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup();"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdTextAreaProps.js"/>
+
+ <broadcaster id="args" value=""/>
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <groupbox><caption label="&Settings.label;"/>
+ <grid><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="TextAreaName" value="&TextAreaName.label;" accesskey="&TextAreaName.accessKey;"/>
+ <textbox id="TextAreaName" oninput="onInput();"/>
+ </row>
+ <row align="center">
+ <label control="TextAreaRows" value="&TextAreaRows.label;" accesskey="&TextAreaRows.accessKey;"/>
+ <hbox>
+ <textbox id="TextAreaRows" class="narrow" oninput="forceInteger(this.id);onInput();"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="TextAreaCols" value="&TextAreaCols.label;" accesskey="&TextAreaCols.accessKey;"/>
+ <hbox>
+ <textbox id="TextAreaCols" class="narrow" oninput="forceInteger(this.id);onInput();"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ <hbox>
+ <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
+ </hbox>
+ <grid id="MoreSection"><columns><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label control="TextAreaWrap" value="&TextAreaWrap.label;" accesskey="&TextAreaWrap.accessKey;"/>
+ <menulist id="TextAreaWrap">
+ <menupopup>
+ <menuitem label="&WrapDefault.value;"/>
+ <menuitem label="&WrapOff.value;" value="off"/>
+ <menuseparator/>
+ <menuitem label="&WrapSoft.value;" value="soft"/>
+ <menuitem label="&WrapHard.value;" value="hard"/>
+ <menuseparator/>
+ <menuitem label="&WrapPhysical.value;" value="physical"/>
+ <menuitem label="&WrapVirtual.value;" value="virtual"/>
+ <menuseparator/>
+ <menuitem label="normal" value="normal"/>
+ <menuitem label="nowrap" value="nowrap"/>
+ <menuitem label="pre" value="pre"/>
+ </menupopup>
+ </menulist>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="TextAreaReadOnly" label="&TextAreaReadOnly.label;" accesskey="&TextAreaReadOnly.accessKey;"/>
+ </row>
+ <row>
+ <spacer/>
+ <checkbox id="TextAreaDisabled" label="&TextAreaDisabled.label;" accesskey="&TextAreaDisabled.accessKey;"/>
+ </row>
+ <row align="center">
+ <label control="TextAreaTabIndex" value="&TextAreaTabIndex.label;" accesskey="&TextAreaTabIndex.accessKey;"/>
+ <hbox>
+ <textbox id="TextAreaTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
+ </hbox>
+ </row>
+ <row align="center">
+ <label control="TextAreaAccessKey" value="&TextAreaAccessKey.label;" accesskey="&TextAreaAccessKey.accessKey;"/>
+ <hbox>
+ <textbox id="TextAreaAccessKey" class="narrow" maxlength="1"/>
+ </hbox>
+ </row>
+ <row>
+ <label control="TextAreaValue" value="&InitialText.label;" accesskey="&InitialText.accessKey;"/>
+ </row>
+ <textbox id="TextAreaValue" flex="1" multiline="true" rows="5"/>
+ </rows>
+ </grid>
+ </groupbox>
+
+ <!-- from EdDialogOverlay -->
+ <vbox id="AdvancedEdit"/>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditConflict.js
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// dialog initialization code
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+
+ SetWindowLocation();
+}
+
+function KeepCurrentPage()
+{
+ // Simply close dialog and don't change current page
+ //TODO: Should we force saving of the current page?
+ SaveWindowLocation();
+ return true;
+}
+
+function UseOtherPage()
+{
+ // Reload the URL -- that will get other editor's contents
+ setTimeout("window.opener.EditorLoadUrl(GetDocumentUrl())", 10);
+ SaveWindowLocation();
+ return true;
+}
+
+function PreventCancel()
+{
+ SaveWindowLocation();
+
+ // Don't let Esc key close the dialog!
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditConflict.xul
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditConflict.dtd">
+
+<dialog buttons="cancel" title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogcancel="return onClose();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditConflict.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+
+ <label value ="&conflictWarning.label;"/>
+ <spacer class="bigspacer"/>
+ <label value ="&conflictResolve.label;"/>
+ <spacer class="bigspacer"/>
+ <hbox flex="1">
+ <spacer class="bigspacer"/>
+ <button label="&keepCurrentPageButton.label;"
+ oncommand="KeepCurrentPage()"/>
+ <spacer class="bigspacer"/>
+ </hbox>
+ <hbox flex="1">
+ <spacer class="bigspacer"/>
+ <button dlgtype="cancel"
+ label="&useOtherPageButton.label;"
+ oncommand="UseOtherPage()"/>
+ <spacer class="bigspacer"/>
+ </hbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublish.js
@@ -0,0 +1,589 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charley Manske (cmanske@netscape.com)
+ * Ryan Cassin (rcassin@supernova.org)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gPublishSiteData;
+var gReturnData;
+var gDefaultSiteIndex = -1;
+var gDefaultSiteName;
+var gPreviousDefaultDir;
+var gPreviousTitle;
+var gSettingsChanged = false;
+var gInitialSiteName;
+var gInitialSiteIndex = -1;
+var gPasswordManagerOn = true;
+
+// Dialog initialization code
+function Startup()
+{
+ window.opener.ok = false;
+
+ // Element to edit is passed in
+ gInitialSiteName = window.arguments[1];
+ gReturnData = window.arguments[2];
+ if (!gReturnData || !GetCurrentEditor())
+ {
+ dump("Publish: No editor or return data object not supplied\n");
+ window.close();
+ return;
+ }
+
+ gDialog.TabBox = document.getElementById("TabBox");
+ gDialog.PublishTab = document.getElementById("PublishTab");
+ gDialog.SettingsTab = document.getElementById("SettingsTab");
+
+ // Publish panel
+ gDialog.PageTitleInput = document.getElementById("PageTitleInput");
+ gDialog.FilenameInput = document.getElementById("FilenameInput");
+ gDialog.SiteList = document.getElementById("SiteList");
+ gDialog.DocDirList = document.getElementById("DocDirList");
+ gDialog.OtherDirCheckbox = document.getElementById("OtherDirCheckbox");
+ gDialog.OtherDirRadiogroup = document.getElementById("OtherDirRadiogroup");
+ gDialog.SameLocationRadio = document.getElementById("SameLocationRadio");
+ gDialog.UseSubdirRadio = document.getElementById("UseSubdirRadio");
+ gDialog.OtherDirList = document.getElementById("OtherDirList");
+
+ // Settings Panel
+ gDialog.SiteNameInput = document.getElementById("SiteNameInput");
+ gDialog.PublishUrlInput = document.getElementById("PublishUrlInput");
+ gDialog.BrowseUrlInput = document.getElementById("BrowseUrlInput");
+ gDialog.UsernameInput = document.getElementById("UsernameInput");
+ gDialog.PasswordInput = document.getElementById("PasswordInput");
+ gDialog.SavePassword = document.getElementById("SavePassword");
+
+ gPasswordManagerOn = GetBoolPref("signon.rememberSignons");
+ gDialog.SavePassword.disabled = !gPasswordManagerOn;
+
+ gPublishSiteData = GetPublishSiteData();
+ gDefaultSiteName = GetDefaultPublishSiteName();
+
+ var addNewSite = false;
+ if (gPublishSiteData)
+ {
+ FillSiteList();
+ }
+ else
+ {
+ // No current site data, start a new item in the Settings panel
+ AddNewSite();
+ addNewSite = true;
+ }
+
+ var docUrl = GetDocumentUrl();
+ var scheme = GetScheme(docUrl);
+ var filename = "";
+
+ if (scheme)
+ {
+ filename = GetFilename(docUrl);
+
+ if (scheme != "file")
+ {
+ var siteFound = false;
+
+ // Editing a remote URL.
+ // Attempt to find doc URL in Site Data
+ if (gPublishSiteData)
+ {
+ var dirObj = {};
+ var siteIndex = FindSiteIndexAndDocDir(gPublishSiteData, docUrl, dirObj);
+
+ // Select this site only if the same as user's intended site, or there wasn't one
+ if (siteIndex != -1 && (gInitialSiteIndex == -1 || siteIndex == gInitialSiteIndex))
+ {
+ siteFound = true;
+
+ // Select the site we found
+ gDialog.SiteList.selectedIndex = siteIndex;
+ var docDir = dirObj.value;
+
+ // Use the directory within site in the editable menulist
+ gPublishSiteData[siteIndex].docDir = docDir;
+
+ //XXX HOW DO WE DECIDE WHAT "OTHER" DIR TO USE?
+ //gPublishSiteData[siteIndex].otherDir = docDir;
+ }
+ }
+ if (!siteFound)
+ {
+ // Not found in site database
+ // Setup for a new site and use data from a remote URL
+ if (!addNewSite)
+ AddNewSite();
+
+ addNewSite = true;
+
+ var publishData = CreatePublishDataFromUrl(docUrl);
+ if (publishData)
+ {
+ filename = publishData.filename;
+ gDialog.SiteNameInput.value = publishData.siteName;
+ gDialog.PublishUrlInput.value = publishData.publishUrl;
+ gDialog.BrowseUrlInput.value = publishData.browseUrl;
+ gDialog.UsernameInput.value = publishData.username;
+ gDialog.PasswordInput.value = publishData.password;
+ gDialog.SavePassword.checked = false;
+ }
+ }
+ }
+ }
+ try {
+ gPreviousTitle = GetDocumentTitle();
+ } catch (e) {}
+
+ gDialog.PageTitleInput.value = gPreviousTitle;
+ gDialog.FilenameInput.value = decodeURIComponent(filename);
+
+ if (!addNewSite)
+ {
+ // If not adding a site and we haven't selected a site -- use initial or default site
+ if (gDialog.SiteList.selectedIndex == -1)
+ gDialog.SiteList.selectedIndex = (gInitialSiteIndex != -1) ? gInitialSiteIndex : gDefaultSiteIndex;
+
+ // Fill in all the site data for currently-selected site
+ SelectSiteList();
+ SetTextboxFocus(gDialog.PageTitleInput);
+ }
+
+ if (gDialog.SiteList.selectedIndex == -1)
+ {
+ // No selected site -- assume same directory
+ gDialog.OtherDirRadiogroup.selectedItem = gDialog.SameLocationRadio;
+ }
+ else if (gPublishSiteData[gDialog.SiteList.selectedIndex].docDir ==
+ gPublishSiteData[gDialog.SiteList.selectedIndex].otherDir)
+ {
+ // For now, check "same location" if dirs are already set to same directory
+ gDialog.OtherDirRadiogroup.selectedItem = gDialog.SameLocationRadio;
+ }
+ else
+ {
+ gDialog.OtherDirRadiogroup.selectedItem = gDialog.UseSubdirRadio;
+ }
+
+ doEnabling();
+
+ SetWindowLocation();
+}
+
+function FillSiteList()
+{
+ gDialog.SiteList.removeAllItems();
+ gDefaultSiteIndex = -1;
+
+ // Fill the site lists
+ var count = gPublishSiteData.length;
+ var i;
+
+ for (i = 0; i < count; i++)
+ {
+ var name = gPublishSiteData[i].siteName;
+ var menuitem = gDialog.SiteList.appendItem(name);
+ // Highlight the default site
+ if (name == gDefaultSiteName)
+ {
+ gDefaultSiteIndex = i;
+ if (menuitem)
+ {
+ menuitem.setAttribute("class", "menuitem-highlight-1");
+ menuitem.setAttribute("default", "true");
+ }
+ }
+ // Find initial site location
+ if (name == gInitialSiteName)
+ gInitialSiteIndex = i;
+ }
+}
+
+function doEnabling()
+{
+ var disableOther = !gDialog.OtherDirCheckbox.checked;
+ gDialog.SameLocationRadio.disabled = disableOther;
+ gDialog.UseSubdirRadio.disabled = disableOther;
+ gDialog.OtherDirList.disabled = (disableOther || gDialog.SameLocationRadio.selected);
+}
+
+function SelectSiteList()
+{
+ var selectedSiteIndex = gDialog.SiteList.selectedIndex;
+
+ var siteName = "";
+ var publishUrl = "";
+ var browseUrl = "";
+ var username = "";
+ var password = "";
+ var savePassword = false;
+ var publishOtherFiles = true;
+
+ gDialog.DocDirList.removeAllItems();
+ gDialog.OtherDirList.removeAllItems();
+
+ if (gPublishSiteData && selectedSiteIndex != -1)
+ {
+ siteName = gPublishSiteData[selectedSiteIndex].siteName;
+ publishUrl = gPublishSiteData[selectedSiteIndex].publishUrl;
+ browseUrl = gPublishSiteData[selectedSiteIndex].browseUrl;
+ username = gPublishSiteData[selectedSiteIndex].username;
+ savePassword = gPasswordManagerOn ? gPublishSiteData[selectedSiteIndex].savePassword : false;
+ if (savePassword)
+ password = gPublishSiteData[selectedSiteIndex].password;
+
+ // Fill the directory menulists
+ if (gPublishSiteData[selectedSiteIndex].dirList.length)
+ {
+ for (var i = 0; i < gPublishSiteData[selectedSiteIndex].dirList.length; i++)
+ {
+ gDialog.DocDirList.appendItem(gPublishSiteData[selectedSiteIndex].dirList[i]);
+ gDialog.OtherDirList.appendItem(gPublishSiteData[selectedSiteIndex].dirList[i]);
+ }
+ }
+ gDialog.DocDirList.value = FormatDirForPublishing(gPublishSiteData[selectedSiteIndex].docDir);
+ gDialog.OtherDirList.value = FormatDirForPublishing(gPublishSiteData[selectedSiteIndex].otherDir);
+ publishOtherFiles = gPublishSiteData[selectedSiteIndex].publishOtherFiles;
+
+ }
+ else
+ {
+ gDialog.DocDirList.value = "";
+ gDialog.OtherDirList.value = "";
+ }
+
+ gDialog.SiteNameInput.value = siteName;
+ gDialog.PublishUrlInput.value = publishUrl;
+ gDialog.BrowseUrlInput.value = browseUrl;
+ gDialog.UsernameInput.value = username;
+ gDialog.PasswordInput.value = password;
+ gDialog.SavePassword.checked = savePassword;
+ gDialog.OtherDirCheckbox.checked = publishOtherFiles;
+
+ doEnabling();
+}
+
+function AddNewSite()
+{
+ // Button in Publish panel allows user
+ // to automatically switch to "Settings" panel
+ // to enter data for new site
+ SwitchPanel(gDialog.SettingsTab);
+
+ gDialog.SiteList.selectedIndex = -1;
+
+ SelectSiteList();
+
+ gSettingsChanged = true;
+
+ SetTextboxFocus(gDialog.SiteNameInput);
+}
+
+function SelectPublishTab()
+{
+ if (gSettingsChanged && !ValidateSettings())
+ return;
+
+ SwitchPanel(gDialog.PublishTab);
+ SetTextboxFocus(gDialog.PageTitleInput);
+}
+
+function SelectSettingsTab()
+{
+ SwitchPanel(gDialog.SettingsTab);
+ SetTextboxFocus(gDialog.SiteNameInput);
+}
+
+function SwitchPanel(tab)
+{
+ if (gDialog.TabBox.selectedTab != tab)
+ gDialog.TabBox.selectedTab = tab;
+}
+
+function onInputSettings()
+{
+ // TODO: Save current data during SelectSite and compare here
+ // to detect if real change has occured?
+ gSettingsChanged = true;
+}
+
+function GetPublishUrlInput()
+{
+ gDialog.PublishUrlInput.value = FormatUrlForPublishing(gDialog.PublishUrlInput.value);
+ return gDialog.PublishUrlInput.value;
+}
+
+function GetBrowseUrlInput()
+{
+ gDialog.BrowseUrlInput.value = FormatUrlForPublishing(gDialog.BrowseUrlInput.value);
+ return gDialog.BrowseUrlInput.value;
+}
+
+function GetDocDirInput()
+{
+ gDialog.DocDirList.value = FormatDirForPublishing(gDialog.DocDirList.value);
+ return gDialog.DocDirList.value;
+}
+
+function GetOtherDirInput()
+{
+ gDialog.OtherDirList.value = FormatDirForPublishing(gDialog.OtherDirList.value);
+ return gDialog.OtherDirList.value;
+}
+
+function ChooseDir(menulist)
+{
+ //TODO: For FTP publish destinations, get file listing of just dirs
+ // and build a tree to let user select dir
+}
+
+function ValidateSettings()
+{
+ var siteName = TrimString(gDialog.SiteNameInput.value);
+ if (!siteName)
+ {
+ ShowErrorInPanel(gDialog.SettingsTab, "MissingSiteNameError", gDialog.SiteNameInput);
+ return false;
+ }
+ if (PublishSiteNameExists(siteName, gPublishSiteData, gDialog.SiteList.selectedIndex))
+ {
+ SwitchPanel(gDialog.SettingsTab);
+ ShowInputErrorMessage(GetString("DuplicateSiteNameError").replace(/%name%/, siteName));
+ SetTextboxFocus(gDialog.SiteNameInput);
+ return false;
+ }
+
+ // Extract username and password while removing them from publishingUrl
+ var urlUserObj = {};
+ var urlPassObj = {};
+ var publishUrl = StripUsernamePassword(gDialog.PublishUrlInput.value, urlUserObj, urlPassObj);
+ if (publishUrl)
+ {
+ publishUrl = FormatUrlForPublishing(publishUrl);
+
+ // Assume scheme = "ftp://" if missing
+ // This compensates when user enters hostname w/o scheme (as most ISPs provide)
+ if (!GetScheme(publishUrl))
+ publishUrl = "ftp://" + publishUrl;
+
+ gDialog.PublishUrlInput.value = publishUrl;
+ }
+ else
+ {
+ ShowErrorInPanel(gDialog.SettingsTab, "MissingPublishUrlError", gDialog.PublishUrlInput);
+ return false;
+ }
+ var browseUrl = GetBrowseUrlInput();
+
+ var username = TrimString(gDialog.UsernameInput.value);
+ var savePassword = gDialog.SavePassword.checked;
+ var password = gDialog.PasswordInput.value;
+ var publishOtherFiles = gDialog.OtherDirCheckbox.checked;
+
+ //XXX If there was a username and/or password in the publishUrl
+ // AND in the input field, which do we use?
+ // Let's use those in url only if input is empty
+ if (!username)
+ {
+ username = urlUserObj.value;
+ gDialog.UsernameInput.value = username;
+ gSettingsChanged = true;
+ }
+ if (!password)
+ {
+ password = urlPassObj.value;
+ gDialog.PasswordInput.value = password;
+ gSettingsChanged = true;
+ }
+
+ // Update or add data for a site
+ var siteIndex = gDialog.SiteList.selectedIndex;
+ var newSite = false;
+
+ if (siteIndex == -1)
+ {
+ // No site is selected, add a new site at the end
+ if (gPublishSiteData)
+ {
+ siteIndex = gPublishSiteData.length;
+ }
+ else
+ {
+ // First time: start entire site array
+ gPublishSiteData = new Array(1);
+ siteIndex = 0;
+ gDefaultSiteIndex = 0;
+ gDefaultSiteName = siteName;
+ }
+ gPublishSiteData[siteIndex] = {};
+ gPublishSiteData[siteIndex].docDir = "";
+ gPublishSiteData[siteIndex].otherDir = "";
+ gPublishSiteData[siteIndex].dirList = [""];
+ gPublishSiteData[siteIndex].publishOtherFiles = true;
+ gPublishSiteData[siteIndex].previousSiteName = siteName;
+ newSite = true;
+ }
+ gPublishSiteData[siteIndex].siteName = siteName;
+ gPublishSiteData[siteIndex].publishUrl = publishUrl;
+ gPublishSiteData[siteIndex].browseUrl = browseUrl;
+ gPublishSiteData[siteIndex].username = username;
+ // Don't save password in data that will be saved in prefs
+ gPublishSiteData[siteIndex].password = savePassword ? password : "";
+ gPublishSiteData[siteIndex].savePassword = savePassword;
+
+ if (publishOtherFiles != gPublishSiteData[siteIndex].publishOtherFiles)
+ gSettingsChanged = true;
+
+ gPublishSiteData[siteIndex].publishOtherFiles = publishOtherFiles;
+
+ gDialog.SiteList.selectedIndex = siteIndex;
+ if (siteIndex == gDefaultSiteIndex)
+ gDefaultSiteName = siteName;
+
+ // Should never be empty, but be sure we have a default site
+ if (!gDefaultSiteName)
+ {
+ gDefaultSiteName = gPublishSiteData[0].siteName;
+ gDefaultSiteIndex = 0;
+ }
+
+ // Rebuild the site menulist if we added a new site
+ if (newSite)
+ {
+ FillSiteList();
+ gDialog.SiteList.selectedIndex = siteIndex;
+ }
+ else
+ {
+ // Update selected item if sitename changed
+ var selectedItem = gDialog.SiteList.selectedItem;
+ if (selectedItem)
+ {
+ var oldName = selectedItem.getAttribute("label");
+ if (oldName != siteName)
+ {
+ selectedItem.setAttribute("label", siteName);
+ gDialog.SiteList.setAttribute("label", siteName);
+ gSettingsChanged = true;
+ if (oldName == gDefaultSiteName)
+ gDefaultSiteName = siteName;
+ }
+ }
+ }
+
+ // Get the directory name in site to publish to
+ var docDir = GetDocDirInput();
+
+ gPublishSiteData[siteIndex].docDir = docDir;
+
+ // And directory for images and other files
+ var otherDir = GetOtherDirInput();
+ if (gDialog.SameLocationRadio.selected)
+ otherDir = docDir;
+ else
+ otherDir = GetOtherDirInput();
+
+ gPublishSiteData[siteIndex].otherDir = otherDir;
+
+ // Fill return data object
+ gReturnData.siteName = siteName;
+ gReturnData.previousSiteName = gPublishSiteData[siteIndex].previousSiteName;
+ gReturnData.publishUrl = publishUrl;
+ gReturnData.browseUrl = browseUrl;
+ gReturnData.username = username;
+ // Note that we use the password for the next publish action
+ // even if savePassword is false; but we won't save it in PasswordManager database
+ gReturnData.password = password;
+ gReturnData.savePassword = savePassword;
+ gReturnData.docDir = gPublishSiteData[siteIndex].docDir;
+ gReturnData.otherDir = gPublishSiteData[siteIndex].otherDir;
+ gReturnData.publishOtherFiles = publishOtherFiles;
+ gReturnData.dirList = gPublishSiteData[siteIndex].dirList;
+ return true;
+}
+
+function ValidateData()
+{
+ if (!ValidateSettings())
+ return false;
+
+ var siteIndex = gDialog.SiteList.selectedIndex;
+ if (siteIndex == -1)
+ return false;
+
+ var filename = TrimString(gDialog.FilenameInput.value);
+ if (!filename)
+ {
+ ShowErrorInPanel(gDialog.PublishTab, "MissingPublishFilename", gDialog.FilenameInput);
+ return false;
+ }
+ gReturnData.filename = filename;
+
+ return true;
+}
+
+function ShowErrorInPanel(tab, errorMsgId, widgetWithError)
+{
+ SwitchPanel(tab);
+ ShowInputErrorMessage(GetString(errorMsgId));
+ if (widgetWithError)
+ SetTextboxFocus(widgetWithError);
+}
+
+function onAccept()
+{
+ if (ValidateData())
+ {
+ // DON'T save the docDir and otherDir before trying to publish
+ gReturnData.saveDirs = false;
+
+ // We save new site data to prefs only if we are attempting to publish
+ if (gSettingsChanged)
+ SavePublishDataToPrefs(gReturnData);
+
+ // Set flag to resave data after publishing
+ // so we save docDir and otherDir if we published successfully
+ gReturnData.savePublishData = true;
+
+ var title = TrimString(gDialog.PageTitleInput.value);
+ if (title != gPreviousTitle)
+ SetDocumentTitle(title);
+
+ SaveWindowLocation();
+ window.opener.ok = true;
+ return true;
+ }
+
+ return false;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublish.xul
@@ -0,0 +1,160 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EditorPublishOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPublish.dtd">
+
+<dialog title="&windowTitle.label;"
+ id="publishDlg"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ buttons="accept,cancel"
+ buttonlabelaccept="&publishButton.label;"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditorPublish.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/publishprefs.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <tabbox id="TabBox">
+ <tabs flex="1">
+ <tab id="PublishTab" oncommand="SelectPublishTab()" label="&publishTab.label;"/>
+ <tab id="SettingsTab" oncommand="SelectSettingsTab()" label="&settingsTab.label;"/>
+ </tabs>
+ <tabpanels>
+ <!-- PUBLISH PANEL -->
+ <vbox>
+ <spacer class="spacer"/>
+ <grid pack="start">
+ <columns><column/><column/><column/></columns>
+ <rows>
+ <row align="center">
+ <label value="&siteList.label;"/>
+ <!-- Contents filled in at runtime -->
+ <menulist id="SiteList"
+ style="min-width:18em; max-width:18em;" crop="right"
+ oncommand="SelectSiteList();"/>
+ <hbox>
+ <button label="&newSiteButton.label;"
+ accesskey="&newSiteButton.accesskey;"
+ oncommand="AddNewSite();"/>
+ <spacer flex="1"/>
+ </hbox>
+ </row>
+ <spacer class="spacer"/>
+ <row align="center">
+ <label value="&pageTitle.label;" accesskey="&pageTitle.accesskey;"
+ control="PageTitleInput"/>
+ <textbox id="PageTitleInput"
+ tooltiptext="&pageTitle.tooltip;" class="minWidth15"/>
+ <label value="&pageTitleExample.label;"/>
+ </row>
+ <row align="center">
+ <label value="&filename.label;" accesskey="&filename.accesskey;"
+ control="FilenameInput"/>
+ <textbox id="FilenameInput"
+ tooltiptext="&filename.tooltip;" class="minWidth15 uri-element"/>
+ <label value="&filenameExample.label;"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer class="spacer"/>
+ <label value="&docDirList.label;"/>
+ <hbox align="center">
+ <!-- Contents filled in at runtime -->
+ <menulist id="DocDirList" class="minWidth20 uri-element" editable="true" flex="1"
+ tooltiptext="&docDirList.tooltip;" oninput="onInputSettings();"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <groupbox>
+ <caption>
+ <checkbox id="OtherDirCheckbox" label="&publishImgCheckbox.label;"
+ accesskey="&publishImgCheckbox.accesskey;"
+ tooltiptext="&publishImgCheckbox.tooltip;"
+ oncommand="doEnabling();"/>
+ </caption>
+ <vbox>
+ <radiogroup id="OtherDirRadiogroup">
+ <hbox>
+ <spacer class="checkbox-spacer"/>
+ <radio id="SameLocationRadio" label="&sameLocationRadio.label;"
+ accesskey="&sameLocationRadio.accesskey;"
+ tooltiptext="&sameLocationRadio.tooltip;"
+ oncommand="doEnabling();"/>
+ </hbox>
+ <hbox>
+ <spacer class="checkbox-spacer"/>
+ <radio id="UseSubdirRadio" label="&useSubdirRadio.label;"
+ accesskey="&useSubdirRadio.accesskey;"
+ tooltiptext="&useSubdirRadio.tooltip;"
+ oncommand="doEnabling();"/>
+ </hbox>
+ </radiogroup>
+ </vbox>
+ <hbox>
+ <spacer class="checkbox-spacer"/>
+ <spacer class="radio-spacer"/>
+ <!-- Contents filled in at runtime -->
+ <menulist id="OtherDirList" class="minWidth20 uri-element"
+ editable="true" flex="1" tooltiptext="&otherDirList.tooltip;"
+ oninput="onInputSettings();"/>
+ </hbox>
+ </groupbox>
+ <spacer flex="1"/>
+ </vbox><!-- Publish Panel -->
+
+ <!-- SETTINGS PANEL -->
+ <hbox id="SettingsPanel">
+ <!-- from EditorPublishOverlay.xul -->
+ <vbox id="PublishSettingsInputs" flex="1"/>
+ </hbox><!-- Settings Panel -->
+ </tabpanels>
+ </tabbox>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublishOverlay.xul
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://editor/locale/EditorPublish.dtd">
+
+<overlay id="EditorPublishOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<vbox id="PublishSettingsInputs">
+ <groupbox id="ServerSettingsBox">
+ <caption label="&serverInfo.label;"/>
+ <hbox align="center">
+ <label value="&siteName.label;" accesskey="&siteName.accesskey;"
+ control="SiteNameInput"/>
+ <textbox id="SiteNameInput" class="MinWidth20em" flex="1"
+ tooltiptext="&siteName.tooltip;" oninput="onInputSettings();"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <label value="&siteUrl.label;" accesskey="&siteUrl.accesskey;"
+ control="PublishUrlInput"/>
+ <textbox id="PublishUrlInput" class="MinWidth20em uri-element"
+ tooltiptext="&siteUrl.tooltip;" oninput="onInputSettings();"/>
+ <spacer class="spacer"/>
+ <label value="&browseUrl.label;" accesskey="&browseUrl.accesskey;"
+ control="BrowseUrlInput"/>
+ <textbox id="BrowseUrlInput" class="MinWidth20em uri-element"
+ tooltiptext="&browseUrl.tooltip;" oninput="onInputSettings();"/>
+ <spacer class="spacer"/>
+ </groupbox>
+ <groupbox id="LoginSettingsBox">
+ <caption label="&loginInfo.label;"/>
+ <grid>
+ <columns><column flex="1"/><column flex="3"/></columns>
+ <rows>
+ <row align="center">
+ <label value="&username.label;" accesskey="&username.accesskey;"
+ control="UsernameInput"/>
+ <textbox id="UsernameInput" class="MinWidth10em" flex="1"
+ tooltiptext="&username.tooltip;" oninput="onInputSettings();"/>
+ </row>
+ <row align="center">
+ <label value="&password.label;" accesskey="&password.accesskey;"
+ control="PasswordInput"/>
+ <hbox>
+ <textbox id="PasswordInput" type="password" class="MinWidth5em"
+ oninput="onInputSettings();"/>
+ <checkbox id="SavePassword" label="&savePassword.label;"
+ accesskey="&savePassword.accesskey;"
+ tooltiptext="&savePassword.tooltip;"
+ oncommand="onInputSettings();"/>
+ </hbox>
+ </row>
+ </rows>
+ </grid>
+ <spacer class="spacer"/>
+ </groupbox>
+</vbox>
+
+</overlay>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublishProgress.js
@@ -0,0 +1,435 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Charles Manske (cmanske@netscape.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gInProgress = true;
+var gPublishData;
+var gPersistObj;
+var gTotalFileCount = 0;
+var gSucceededCount = 0;
+var gFinished = false;
+var gPublishingFailed = false;
+var gFileNotFound = false;
+var gStatusMessage="";
+
+var gTimerID;
+var gAllowEnterKey = false;
+
+// Publishing error codes
+// These are translated from C++ error code strings like this:
+// kFileNotFound = "FILE_NOT_FOUND",
+const kNetReset = 2152398868; // nsISocketTransportService.idl
+const kFileNotFound = 2152857618;
+const kNotConnected = 2152398860; // in netCore.h
+const kConnectionRefused = 2152398861; // nsISocketTransportService.idl
+const kNetTimeout = 2152398862; // nsISocketTransportService.idl
+const kNoConnectionOrTimeout = 2152398878;
+const kPortAccessNotAllowed = 2152398867; // netCore.h
+const kOffline = 2152398865; // netCore.h
+const kDiskFull = 2152857610;
+const kNoDeviceSpace = 2152857616;
+const kNameTooLong = 2152857617;
+const kAccessDenied = 2152857621;
+
+// These are more errors that I don't think we encounter during publishing,
+// so we don't have error strings yet. Let's keep them here for future reference
+//const kUnrecognizedPath = 2152857601;
+//const kUnresolvableSymlink = 2152857602;
+//const kUnknownType = 2152857604;
+//const kDestinationNotDir = 2152857605;
+//const kTargetDoesNotExist = 2152857606;
+//const kAlreadyExists = 2152857608;
+//const kInvalidPath = 2152857609;
+//const kNotDirectory = 2152857612;
+//const kIsDirectory = 2152857613;
+//const kIsLocked = 2152857614;
+//const kTooBig = 2152857615;
+//const kReadOnly = 2152857619;
+//const kDirectoryNotEmpty = 2152857620;
+//const kErrorBindingRedirected = 2152398851;
+//const kAlreadyConnected = 2152398859; // in netCore.h
+//const kInProgress = 2152398863; // netCore.h
+//const kNoContent = 2152398865; // netCore.h
+//const kUnknownProtocol = 2152398866 // netCore.h
+//const kFtpLogin = 2152398869; // ftpCore.h
+//const kFtpCWD = 2152398870; // ftpCore.h
+//const kFtpPasv = 2152398871; // ftpCore.h
+//const kFtpPwd = 2152398872; // ftpCore.h
+
+
+function Startup()
+{
+ gPublishData = window.arguments[0];
+ if (!gPublishData)
+ {
+ dump("No publish data!\n");
+ window.close();
+ return;
+ }
+
+ gDialog.FileList = document.getElementById("FileList");
+ gDialog.FinalStatusMessage = document.getElementById("FinalStatusMessage");
+ gDialog.StatusMessage = document.getElementById("StatusMessage");
+ gDialog.KeepOpen = document.getElementById("KeepOpen");
+ gDialog.Close = document.documentElement.getButton("cancel");
+
+ SetWindowLocation();
+ var title = GetDocumentTitle();
+ if (!title)
+ title = "("+GetString("untitled")+")";
+ document.title = GetString("PublishProgressCaption").replace(/%title%/, title);
+
+ document.getElementById("PublishToSite").value =
+ GetString("PublishToSite").replace(/%title%/, TruncateStringAtWordEnd(gPublishData.siteName, 25));
+
+ // Show publishing destination URL
+ document.getElementById("PublishUrl").value = gPublishData.publishUrl;
+
+ // Show subdirectories only if not empty
+ if (gPublishData.docDir || gPublishData.otherDir)
+ {
+ if (gPublishData.docDir)
+ document.getElementById("docDir").value = gPublishData.docDir;
+ else
+ document.getElementById("DocSubdir").hidden = true;
+
+ if (gPublishData.publishOtherFiles && gPublishData.otherDir)
+ document.getElementById("otherDir").value = gPublishData.otherDir;
+ else
+ document.getElementById("OtherSubdir").hidden = true;
+ }
+ else
+ document.getElementById("Subdirectories").hidden = true;
+
+ // Add the document to the "publish to" list as quick as possible!
+ SetProgressStatus(gPublishData.filename, "busy");
+
+ if (gPublishData.publishOtherFiles)
+ {
+ // When publishing images as well, expand list to show more items
+ gDialog.FileList.setAttribute("rows", 5);
+ window.sizeToContent();
+ }
+
+ // Now that dialog is initialized, we can start publishing
+ gPersistObj = window.opener.StartPublishing();
+}
+
+// this function is to be used when we cancel persist's saving
+// since not all messages will be returned to us if we cancel
+// this function changes status for all non-done/non-failure to failure
+function SetProgressStatusCancel()
+{
+ var listitems = document.getElementsByTagName("listitem");
+ if (!listitems)
+ return;
+
+ for (var i=0; i < listitems.length; i++)
+ {
+ var attr = listitems[i].getAttribute("progress");
+ if (attr != "done" && attr != "failed")
+ listitems[i].setAttribute("progress", "failed");
+ }
+}
+
+// Add filename to list of files to publish
+// or set status for file already in the list
+// Returns true if file was in the list
+function SetProgressStatus(filename, status)
+{
+ if (!filename)
+ return false;
+
+ if (!status)
+ status = "busy";
+
+ // Just set attribute for status icon
+ // if we already have this filename
+ var listitems = document.getElementsByTagName("listitem");
+ if (listitems)
+ {
+ for (var i=0; i < listitems.length; i++)
+ {
+ if (listitems[i].getAttribute("label") == filename)
+ {
+ listitems[i].setAttribute("progress", status);
+ return true;
+ }
+ }
+ }
+ // We're adding a new file item to list
+ gTotalFileCount++;
+
+ var listitem = document.createElementNS(XUL_NS, "listitem");
+ if (listitem)
+ {
+ listitem.setAttribute("class", "listitem-iconic progressitem");
+ // This triggers CSS to show icon for each status state
+ listitem.setAttribute("progress", status);
+ listitem.setAttribute("label", filename);
+ gDialog.FileList.appendChild(listitem);
+ }
+ return false;
+}
+
+function SetProgressFinished(filename, networkStatus)
+{
+ var abortPublishing = false;
+ if (filename)
+ {
+ var status = networkStatus ? "failed" : "done";
+ if (networkStatus == 0)
+ gSucceededCount++;
+
+ SetProgressStatus(filename, status);
+ }
+
+ if (networkStatus != 0) // Error condition
+ {
+ // We abort on all errors except if image file was not found
+ abortPublishing = networkStatus != kFileNotFound;
+
+ // Mark all remaining files as "failed"
+ if (abortPublishing)
+ {
+ gPublishingFailed = true;
+ SetProgressStatusCancel();
+ gDialog.FinalStatusMessage.value = GetString("PublishFailed");
+ }
+
+ switch (networkStatus)
+ {
+ case kFileNotFound:
+ gFileNotFound = true;
+ if (filename)
+ gStatusMessage = GetString("FileNotFound").replace(/%file%/, filename);
+ break;
+ case kNetReset:
+ // We get this when subdir doesn't exist AND
+ // if filename used is same as an existing subdir
+ var dir = (gPublishData.filename == filename) ?
+ gPublishData.docDir : gPublishData.otherDir;
+
+ if (dir)
+ {
+ // This is the ambiguous case when we can't tell if subdir or filename is bad
+ // Remove terminal "/" from dir string and insert into message
+ gStatusMessage = GetString("SubdirDoesNotExist").replace(/%dir%/, dir.slice(0, dir.length-1));
+ gStatusMessage = gStatusMessage.replace(/%file%/, filename);
+
+ // Remove directory from saved prefs
+ // XXX Note that if subdir is good,
+ // but filename = next level subdirectory name,
+ // we really shouldn't remove subdirectory,
+ // but it's impossible to differentiate this case!
+ RemovePublishSubdirectoryFromPrefs(gPublishData, dir);
+ }
+ else if (filename)
+ gStatusMessage = GetString("FilenameIsSubdir").replace(/%file%/, filename);
+
+ break;
+ case kNotConnected:
+ case kConnectionRefused:
+ case kNetTimeout:
+ case kNoConnectionOrTimeout:
+ case kPortAccessNotAllowed:
+ gStatusMessage = GetString("ServerNotAvailable");
+ break;
+ case kOffline:
+ gStatusMessage = GetString("Offline");
+ break;
+ case kDiskFull:
+ case kNoDeviceSpace:
+ if (filename)
+ gStatusMessage = GetString("DiskFull").replace(/%file%/, filename);
+ break;
+ case kNameTooLong:
+ if (filename)
+ gStatusMessage = GetString("NameTooLong").replace(/%file%/, filename);
+ break;
+ case kAccessDenied:
+ if (filename)
+ gStatusMessage = GetString("AccessDenied").replace(/%file%/, filename);
+ break;
+ case kUnknownType:
+ default:
+ gStatusMessage = GetString("UnknownPublishError")
+ break;
+ }
+ }
+ else if (!filename)
+ {
+ gFinished = true;
+
+ document.documentElement.setAttribute("buttonlabelcancel",
+ document.documentElement.getAttribute("buttonlabelclose"));
+
+ if (!gStatusMessage)
+ gStatusMessage = GetString(gPublishingFailed ? "UnknownPublishError" : "AllFilesPublished");
+
+ // Now allow "Enter/Return" key to close the dialog
+ AllowDefaultButton();
+
+ if (gPublishingFailed || gFileNotFound)
+ {
+ // Show "Troubleshooting" button to help solving problems
+ // and key for successful / failed files
+ document.getElementById("failureBox").hidden = false;
+ }
+ }
+
+ if (gStatusMessage)
+ SetStatusMessage(gStatusMessage);
+}
+
+function CheckKeepOpen()
+{
+ if (gTimerID)
+ {
+ clearTimeout(gTimerID);
+ gTimerID = null;
+ }
+}
+
+function onClose()
+{
+ if (!gFinished)
+ {
+ const nsIPromptService = Components.interfaces.nsIPromptService;
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(nsIPromptService);
+ const buttonFlags = (nsIPromptService.BUTTON_TITLE_IS_STRING *
+ nsIPromptService.BUTTON_POS_0) +
+ (nsIPromptService.BUTTON_TITLE_CANCEL *
+ nsIPromptService.BUTTON_POS_1);
+ var button = promptService.confirmEx(window,
+ GetString("CancelPublishTitle"),
+ GetString("CancelPublishMessage"),
+ buttonFlags,
+ GetString("CancelPublishContinue"),
+ null, null, null, {});
+ if (button == 0)
+ return false;
+ }
+
+ if (gTimerID)
+ {
+ clearTimeout(gTimerID);
+ gTimerID = null;
+ }
+
+ if (!gFinished && gPersistObj)
+ {
+ try {
+ gPersistObj.cancelSave();
+ } catch (e) {}
+ }
+ SaveWindowLocation();
+
+ // Tell caller so they can cleanup and restore editability
+ window.opener.FinishPublishing();
+ return true;
+}
+
+function AllowDefaultButton()
+{
+ gDialog.Close.setAttribute("default","true");
+ gAllowEnterKey = true;
+}
+
+function onEnterKey()
+{
+ if (gAllowEnterKey)
+ return CloseDialog();
+
+ return false;
+}
+
+function RequestCloseDialog()
+{
+ // Finish progress messages, settings buttons etc.
+ SetProgressFinished(null, 0);
+
+ if (!gDialog.KeepOpen.checked)
+ {
+ // Leave window open a minimum amount of time
+ gTimerID = setTimeout("CloseDialog();", 3000);
+ }
+
+ // Set "completed" message if we succeeded
+ // (Some image files may have failed,
+ // but we don't abort publishing for that)
+ if (!gPublishingFailed)
+ {
+ gDialog.FinalStatusMessage.value = GetString("PublishCompleted");
+ if (gFileNotFound && gTotalFileCount-gSucceededCount)
+ {
+ // Show number of files that failed to upload
+ gStatusMessage =
+ (GetString("FailedFileMsg").replace(/%x%/,(gTotalFileCount-gSucceededCount)))
+ .replace(/%total%/,gTotalFileCount);
+
+ SetStatusMessage(gStatusMessage);
+ }
+ }
+}
+
+function SetStatusMessage(message)
+{
+ // Status message is a child of <description> element
+ // so text can wrap to multiple lines if necessary
+ if (gDialog.StatusMessage.firstChild)
+ {
+ gDialog.StatusMessage.firstChild.data = message;
+ }
+ else
+ {
+ var textNode = document.createTextNode(message);
+ if (textNode)
+ gDialog.StatusMessage.appendChild(textNode);
+ }
+ window.sizeToContent();
+}
+
+function CloseDialog()
+{
+ SaveWindowLocation();
+ window.opener.FinishPublishing();
+ try {
+ window.close();
+ } catch (e) {}
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublishProgress.xul
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manxke (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPublishProgress.dtd">
+<!-- dialog containing a control requiring initial setup -->
+<dialog title=""
+ id="publishProgressDlg"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ buttons="cancel"
+ buttonlabelclose="&closeButton.label;"
+ onload="Startup()"
+ ondialogaccept="return onEnterKey();"
+ ondialogcancel="return onClose();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/publishprefs.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditorPublishProgress.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <groupbox>
+ <caption><label id="PublishToSite"/></caption>
+ <label value="&siteUrl.label;"/>
+ <hbox>
+ <label class="indent bold" id="PublishUrl"/>
+ </hbox>
+ <spacer class="spacer"/>
+ <grid id="Subdirectories">
+ <columns><column/><column/></columns>
+ <rows>
+ <row id="DocSubdir">
+ <label value="&docSubdir.label;"/>
+ <label id="docDir"/>
+ </row>
+ <row id="OtherSubdir">
+ <label value="&otherSubdir.label;"/>
+ <label id="otherDir"/>
+ </row>
+ </rows>
+ </grid>
+ <label id="OtherUrl" class="bold" style="margin-left:3em"/>
+ </groupbox>
+ <groupbox>
+ <caption><label value="&fileList.label;"/></caption>
+ <vbox align="center" style="max-width:30em">
+ <label id="FinalStatusMessage" class="bold" value="&status.label;"/>
+ </vbox>
+ <description id="StatusMessage" class="wrap" style="max-width:30em; min-height: 1em"/>
+ <vbox flex="1">
+ <listbox id="FileList" rows="1"/>
+ </vbox>
+ <hbox align="center" id="failureBox" hidden="true">
+ <image class="progressitem" progress="done"/>
+ <label value="&succeeded.label;"/>
+ <spacer class="bigspacer"/>
+ <image class="progressitem" progress="failed"/>
+ <label value="&failed.label;"/>
+ </hbox>
+ </groupbox>
+ <checkbox id="KeepOpen" label="&keepOpen;" oncommand="CheckKeepOpen();" persist="checked"/>
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublishSettings.js
@@ -0,0 +1,373 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gPublishSiteData;
+var gPublishDataChanged = false;
+var gDefaultSiteIndex = -1;
+var gDefaultSiteName;
+var gPreviousDefaultSite;
+var gPreviousTitle;
+var gSettingsChanged = false;
+var gSiteDataChanged = false;
+var gAddNewSite = false;
+var gCurrentSiteIndex = -1;
+var gPasswordManagerOn = true;
+
+// Dialog initialization code
+function Startup()
+{
+ if (!GetCurrentEditor())
+ {
+ window.close();
+ return;
+ }
+
+ gDialog.SiteList = document.getElementById("SiteList");
+ gDialog.SiteNameInput = document.getElementById("SiteNameInput");
+ gDialog.PublishUrlInput = document.getElementById("PublishUrlInput");
+ gDialog.BrowseUrlInput = document.getElementById("BrowseUrlInput");
+ gDialog.UsernameInput = document.getElementById("UsernameInput");
+ gDialog.PasswordInput = document.getElementById("PasswordInput");
+ gDialog.SavePassword = document.getElementById("SavePassword");
+ gDialog.SetDefaultButton = document.getElementById("SetDefaultButton");
+ gDialog.RemoveSiteButton = document.getElementById("RemoveSiteButton");
+ gDialog.OkButton = document.documentElement.getButton("accept");
+
+ gPublishSiteData = GetPublishSiteData();
+ gDefaultSiteName = GetDefaultPublishSiteName();
+ gPreviousDefaultSite = gDefaultSiteName;
+
+ gPasswordManagerOn = GetBoolPref("signon.rememberSignons");
+ gDialog.SavePassword.disabled = !gPasswordManagerOn;
+
+ InitDialog();
+
+ SetWindowLocation();
+}
+
+function InitDialog()
+{
+ // If there's no current site data, start a new item in the Settings panel
+ if (!gPublishSiteData)
+ {
+ AddNewSite();
+ }
+ else
+ {
+ FillSiteList();
+
+ // uncomment next code line if you want preselection of the default
+ // publishing site
+ //InitSiteSettings(gDefaultSiteIndex);
+
+ SetTextboxFocus(gDialog.SiteNameInput);
+ }
+}
+
+function FillSiteList()
+{
+ // Prevent triggering SelectSiteList() actions
+ gIsSelecting = true;
+ ClearListbox(gDialog.SiteList);
+ gIsSelecting = false;
+ gDefaultSiteIndex = -1;
+
+ // Fill the site list
+ var count = gPublishSiteData.length;
+ for (var i = 0; i < count; i++)
+ {
+ var name = gPublishSiteData[i].siteName;
+ var item = gDialog.SiteList.appendItem(name);
+ SetPublishItemStyle(item);
+ if (name == gDefaultSiteName)
+ gDefaultSiteIndex = i;
+ }
+}
+
+function SetPublishItemStyle(item)
+{
+ // Display default site with bold style
+ if (item)
+ {
+ if (item.getAttribute("label") == gDefaultSiteName)
+ item.setAttribute("class", "bold");
+ else
+ item.removeAttribute("class");
+ }
+}
+
+function AddNewSite()
+{
+ // Save any pending changes locally first
+ if (!ApplyChanges())
+ return;
+
+ // Initialize Setting widgets to none of the selected sites
+ InitSiteSettings(-1);
+ gAddNewSite = true;
+
+ SetTextboxFocus(gDialog.SiteNameInput);
+}
+
+function RemoveSite()
+{
+ if (!gPublishSiteData)
+ return;
+
+ var index = gDialog.SiteList.selectedIndex;
+ var item;
+ if (index != -1)
+ {
+ item = gDialog.SiteList.selectedItems[0];
+ var nameToRemove = item.getAttribute("label");
+
+ // Remove one item from site data array
+ gPublishSiteData.splice(index, 1);
+ // Remove item from site list
+ gDialog.SiteList.clearSelection();
+ gDialog.SiteList.removeItemAt(index);
+
+ // Adjust if we removed last item and reselect a site
+ if (index >= gPublishSiteData.length)
+ index--;
+ InitSiteSettings(index);
+
+ if (nameToRemove == gDefaultSiteName)
+ {
+ // Deleting current default -- set to new selected item
+ // Arbitrary, but what else to do?
+ SetDefault();
+ }
+ gSiteDataChanged = true;
+ }
+}
+
+function SetDefault()
+{
+ if (!gPublishSiteData)
+ return;
+
+ var index = gDialog.SiteList.selectedIndex;
+ if (index != -1)
+ {
+ gDefaultSiteIndex = index;
+ gDefaultSiteName = gPublishSiteData[index].siteName;
+
+ // Set bold style on new default
+ var item = gDialog.SiteList.firstChild;
+ while (item)
+ {
+ SetPublishItemStyle(item);
+ item = item.nextSibling;
+ }
+ }
+}
+
+// Recursion prevention:
+// Use when you don't want to trigger ApplyChanges and InitSiteSettings
+var gIsSelecting = false;
+
+function SelectSiteList()
+{
+ if (gIsSelecting)
+ return;
+
+ gIsSelecting = true;
+ var newIndex = gDialog.SiteList.selectedIndex;
+
+ // Save any pending changes locally first
+ if (!ApplyChanges())
+ return;
+
+ InitSiteSettings(newIndex);
+
+ gIsSelecting = false;
+}
+
+// Use this to prevent recursion in SelectSiteList
+function SetSelectedSiteIndex(index)
+{
+ gIsSelecting = true;
+ gDialog.SiteList.selectedIndex = index;
+ gIsSelecting = false;
+}
+
+function InitSiteSettings(selectedSiteIndex)
+{
+ // Index to the site we will need to update if settings changed
+ gCurrentSiteIndex = selectedSiteIndex;
+
+ SetSelectedSiteIndex(selectedSiteIndex);
+ var haveData = (gPublishSiteData && selectedSiteIndex != -1);
+
+ gDialog.SiteNameInput.value = haveData ? gPublishSiteData[selectedSiteIndex].siteName : "";
+ gDialog.PublishUrlInput.value = haveData ? gPublishSiteData[selectedSiteIndex].publishUrl : "";
+ gDialog.BrowseUrlInput.value = haveData ? gPublishSiteData[selectedSiteIndex].browseUrl : "";
+ gDialog.UsernameInput.value = haveData ? gPublishSiteData[selectedSiteIndex].username : "";
+
+ var savePassord = haveData && gPasswordManagerOn;
+ gDialog.PasswordInput.value = savePassord ? gPublishSiteData[selectedSiteIndex].password : "";
+ gDialog.SavePassword.checked = savePassord ? gPublishSiteData[selectedSiteIndex].savePassword : false;
+
+ gDialog.SetDefaultButton.disabled = !haveData;
+ gDialog.RemoveSiteButton.disabled = !haveData;
+ gSettingsChanged = false;
+}
+
+function onInputSettings()
+{
+ // TODO: Save current data during SelectSite1 and compare here
+ // to detect if real change has occurred?
+ gSettingsChanged = true;
+}
+
+function ApplyChanges()
+{
+ if (gSettingsChanged && !UpdateSettings())
+ {
+ // Restore selection to previously current site
+ SetSelectedSiteIndex(gCurrentSiteIndex);
+ return false;
+ }
+ return true;
+}
+
+function UpdateSettings()
+{
+ // Validate and add new site
+ var newName = TrimString(gDialog.SiteNameInput.value);
+ if (!newName)
+ {
+ ShowInputErrorMessage(GetString("MissingSiteNameError"), gDialog.SiteNameInput);
+ return false;
+ }
+ if (PublishSiteNameExists(newName, gPublishSiteData, gCurrentSiteIndex))
+ {
+ ShowInputErrorMessage(GetString("DuplicateSiteNameError").replace(/%name%/, newName));
+ SetTextboxFocus(gDialog.SiteNameInput);
+ return false;
+ }
+
+ var newUrl = FormatUrlForPublishing(gDialog.PublishUrlInput.value);
+ if (!newUrl)
+ {
+ ShowInputErrorMessage(GetString("MissingPublishUrlError"), gDialog.PublishUrlInput);
+ return false;
+ }
+
+ // Start assuming we're updating existing site at gCurrentSiteIndex
+ var newSiteData = false;
+
+ if (!gPublishSiteData)
+ {
+ // First time used - Create the first site profile
+ gPublishSiteData = new Array(1);
+ gCurrentSiteIndex = 0;
+ newSiteData = true;
+ }
+ else if (gCurrentSiteIndex == -1)
+ {
+ // No currently-selected site,
+ // must be adding a new site
+ // Add new data at the end of list
+ gCurrentSiteIndex = gPublishSiteData.length;
+ newSiteData = true;
+ }
+
+ if (newSiteData)
+ {
+ // Init new site profile
+ gPublishSiteData[gCurrentSiteIndex] = {};
+ gPublishSiteData[gCurrentSiteIndex].docDir = "";
+ gPublishSiteData[gCurrentSiteIndex].otherDir = "";
+ gPublishSiteData[gCurrentSiteIndex].dirList = [""];
+ gPublishSiteData[gCurrentSiteIndex].previousSiteName = newName;
+ }
+
+ gPublishSiteData[gCurrentSiteIndex].siteName = newName;
+ gPublishSiteData[gCurrentSiteIndex].publishUrl = newUrl;
+ gPublishSiteData[gCurrentSiteIndex].browseUrl = FormatUrlForPublishing(gDialog.BrowseUrlInput.value);
+ gPublishSiteData[gCurrentSiteIndex].username = TrimString(gDialog.UsernameInput.value);
+ gPublishSiteData[gCurrentSiteIndex].password= gDialog.PasswordInput.value;
+ gPublishSiteData[gCurrentSiteIndex].savePassword = gDialog.SavePassword.checked;
+
+ if (gCurrentSiteIndex == gDefaultSiteIndex)
+ gDefaultSiteName = newName;
+
+ // When adding the very first site, assume that's the default
+ if (gPublishSiteData.length == 1 && !gDefaultSiteName)
+ {
+ gDefaultSiteName = gPublishSiteData[0].siteName;
+ gDefaultSiteIndex = 0;
+ }
+
+ FillSiteList();
+
+ // Select current site in list
+ SetSelectedSiteIndex(gCurrentSiteIndex);
+
+ // Signal saving data to prefs
+ gSiteDataChanged = true;
+
+ // Clear current site flags
+ gSettingsChanged = false;
+ gAddNewSite = false;
+
+ return true;
+}
+
+function onAccept()
+{
+ // Save any pending changes locally first
+ if (!ApplyChanges())
+ return false;
+
+ if (gSiteDataChanged)
+ {
+ // Save all local data to prefs
+ SavePublishSiteDataToPrefs(gPublishSiteData, gDefaultSiteName);
+ }
+ else if (gPreviousDefaultSite != gDefaultSiteName)
+ {
+ // only the default site was changed
+ SetDefaultSiteName(gDefaultSiteName);
+ }
+
+ SaveWindowLocation();
+
+ return true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorPublishSettings.xul
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+<?xul-overlay href="chrome://editor/content/EditorPublishOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPublish.dtd">
+
+<dialog title="&windowTitleSettings.label;"
+ id="publishSettingsDlg"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="Startup()"
+ buttons="accept,cancel"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditorPublishSettings.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/publishprefs.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <hbox id="SettingsPanel">
+ <groupbox align="center">
+ <caption label="&publishSites.label;"/>
+ <!-- XXX: If tree isn't wrapped in vbox, it appears BELOW next vbox -->
+ <vbox flex="1">
+ <listbox rows="4" id="SiteList" flex="1" onselect="SelectSiteList();"/>
+ </vbox>
+ <hbox pack="center">
+ <vbox>
+ <button id="NewSiteButton" label="&newSiteButton.label;"
+ accesskey="&newSiteButton.accesskey;" oncommand="AddNewSite();"/>
+ <button id="SetDefaultButton" label="&setDefaultButton.label;"
+ accesskey="&setDefaultButton.accesskey;" oncommand="SetDefault();"/>
+ <button id="RemoveSiteButton" label="&removeButton.label;"
+ accesskey="&removeButton.accesskey;" oncommand="RemoveSite();"/>
+ </vbox>
+ </hbox>
+ </groupbox>
+ <!-- from EditorPublishOverlay.xul -->
+ <vbox id="PublishSettingsInputs"/>
+ </hbox>
+ <spacer class="spacer"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorSaveAsCharset.js
@@ -0,0 +1,169 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Frank Tang ftang@netscape.com
+ * J.M Betak jbetak@netscape.com
+ * Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+var gCharset="";
+var gTitleWasEdited = false;
+var gCharsetWasChanged = false;
+var gInsertNewContentType = false;
+var gContenttypeElement;
+var gInitDone = false;
+
+//Cancel() is in EdDialogCommon.js
+
+function Startup()
+{
+ var editor = GetCurrentEditor();
+ if (!editor)
+ {
+ window.close();
+ return;
+ }
+
+ var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
+ observerService.notifyObservers(null, "charsetmenu-selected", "other");
+
+ gDialog.TitleInput = document.getElementById("TitleInput");
+ gDialog.charsetTree = document.getElementById('CharsetTree');
+ gDialog.exportToText = document.getElementById('ExportToText');
+
+ gContenttypeElement = GetHTTPEquivMetaElement("content-type");
+ if (!gContenttypeElement && (editor.contentsMIMEType != 'text/plain'))
+ {
+ gContenttypeElement = CreateHTTPEquivMetaElement("content-type");
+ if (!gContenttypeElement )
+ {
+ window.close();
+ return;
+ }
+ gInsertNewContentType = true;
+ }
+
+ try {
+ gCharset = editor.documentCharacterSet;
+ } catch (e) {}
+
+ InitDialog();
+
+ // Use the same text as the messagebox for getting title by regular "Save"
+ document.getElementById("EnterTitleLabel").setAttribute("value",GetString("NeedDocTitle"));
+ // This is an <HTML> element so it wraps -- append a child textnode
+ var helpTextParent = document.getElementById("TitleHelp");
+ var helpText = document.createTextNode(GetString("DocTitleHelp"));
+ if (helpTextParent)
+ helpTextParent.appendChild(helpText);
+
+ // SET FOCUS TO FIRST CONTROL
+ SetTextboxFocus(gDialog.TitleInput);
+
+ gInitDone = true;
+
+ SetWindowLocation();
+}
+
+
+function InitDialog()
+{
+ gDialog.TitleInput.value = GetDocumentTitle();
+
+ var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
+ var tree = gDialog.charsetTree;
+ var index = tree.view.getIndexOfResource(RDF.GetResource(gCharset));
+ if (index >= 0) {
+ tree.view.selection.select(index);
+ tree.treeBoxObject.ensureRowIsVisible(index);
+ }
+}
+
+
+function onAccept()
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ if(gCharsetWasChanged)
+ {
+ try {
+ SetMetaElementContent(gContenttypeElement, "text/html; charset=" + gCharset, gInsertNewContentType, true);
+ editor.documentCharacterSet = gCharset;
+ } catch (e) {}
+ }
+
+ editor.endTransaction();
+
+ if(gTitleWasEdited)
+ SetDocumentTitle(TrimString(gDialog.TitleInput.value));
+
+ window.opener.ok = true;
+ window.opener.exportToText = gDialog.exportToText.checked;
+ SaveWindowLocation();
+ return true;
+}
+
+
+function readRDFString(aDS,aRes,aProp)
+{
+ var n = aDS.GetTarget(aRes, aProp, true);
+ if (n)
+ return n.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
+ else
+ return "";
+}
+
+
+function SelectCharset()
+{
+ if(gInitDone)
+ {
+ try
+ {
+ gCharset = gDialog.charsetTree.builderView.getResourceAtIndex(gDialog.charsetTree.currentIndex).Value;
+ if (gCharset)
+ gCharsetWasChanged = true;
+ }
+ catch(e) {}
+ }
+}
+
+
+function TitleChanged()
+{
+ gTitleWasEdited = true;
+}
new file mode 100644
--- /dev/null
+++ b/editor/ui/dialogs/content/EditorSaveAsCharset.xul
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - loadrunner@betak.net
+ - Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
+<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
+
+<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSaveAsCharset.dtd">
+<!-- dialog containing a control requiring initial setup -->
+<!-- WE SHOULD NOT USE ABSOLUTE WITH AND HEIGHT - USE BOXES INSTEAD? -->
+<dialog title="&windowTitle.label;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload = "Startup()"
+ ondialogaccept="return onAccept();"
+ ondialogcancel="return onCancel();"
+ style="width: 32em;">
+
+ <!-- Methods common to all editor dialogs -->
+ <script type="application/x-javascript" src="chrome://editor/content/editorUtilities.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
+ <script type="application/x-javascript" src="chrome://editor/content/EditorSaveAsCharset.js"/>
+
+ <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
+ <broadcaster id="args" value=""/>
+
+ <groupbox><caption label="&documentTitleTitle.label;"/>
+ <!-- Text labels filled in from editor.properties -->
+ <label id="EnterTitleLabel"/>
+ <textbox id="TitleInput" oninput="TitleChanged();"/>
+ <description id="TitleHelp" class="wrap" style="width:1em" />
+ </groupbox>
+
+ <groupbox flex="1"><caption label="&documentCharsetTitle.label;"/>
+ <label value="&documentCharsetDesc.label;"/>
+ <tree id="CharsetTree" height="148" hidecolumnpicker="true" onselect="SelectCharset();"
+ datasources="rdf:charset-menu" ref="NC:EncodersRoot" flags="dont-build-content">
+ <treecols>
+ <treecol id="CharsetCol" flex="1" hideheader="true"/>
+ </treecols>
+ <template>
+ <rule>
+ <treechildren>
+ <treeitem uri="rdf:*">
+ <treerow>
+ <treecell label="rdf:http://home.netscape.com/NC-rdf#Name"/>
+ </treerow>
+ </treeitem>
+ </treechildren>
+ </rule>
+ </template>
+ </tree>
+ </groupbox>
+
+ <checkbox id="ExportToText" label="&documentExportToText.label;" />
+ <separator class="groove"/>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/editor/ui/jar.mn
@@ -0,0 +1,217 @@
+comm.jar:
+% content editor %content/editor/ xpcnativewrappers=yes
+% overlay chrome://communicator/content/tasksOverlay.xul chrome://editor/content/editorTasksOverlay.xul
+% overlay chrome://messenger/content/mailWindowOverlay.xul chrome://editor/content/editorMailOverlay.xul
+#ifdef MOZ_SUITE
+% overlay chrome://communicator/content/pref/preftree.xul chrome://editor/content/editorPrefsOverlay.xul
+% overlay chrome://communicator/content/pref/preferences.xul chrome://editor/content/editorPrefsOverlay.xul
+% overlay chrome://communicator/content/pref/pref-appearance.xul chrome://editor/content/editorPrefsOverlay.xul
+% overlay chrome://navigator/content/navigatorOverlay.xul chrome://editor/content/editorNavigatorOverlay.xul
+% content editor-region %content/editor-region/ xpcnativewrappers=yes
+#endif
+ content/editor/editor.xul (composer/content/editor.xul)
+ content/editor/editor.js (composer/content/editor.js)
+ content/editor/publishprefs.js (composer/content/publishprefs.js)
+ content/editor/editorUtilities.js (composer/content/editorUtilities.js)
+ content/editor/ComposerCommands.js (composer/content/ComposerCommands.js)
+ content/editor/EditorContextMenu.js (composer/content/EditorContextMenu.js)
+ content/editor/EditorContextMenuOverlay.xul (composer/content/EditorContextMenuOverlay.xul)
+ content/editor/EditorAllTags.css (composer/content/EditorAllTags.css)
+ content/editor/EditorParagraphMarks.css (composer/content/EditorParagraphMarks.css)
+ content/editor/EditorContent.css (composer/content/EditorContent.css)
+* content/editor/editorOverlay.xul (composer/content/editorOverlay.xul)
+ content/editor/editorOverlay.js (composer/content/editorOverlay.js)
+ content/editor/composerOverlay.xul (composer/content/composerOverlay.xul)
+ content/editor/pref-toolbars.xul (composer/content/pref-toolbars.xul)
+ content/editor/pref-editing.xul (composer/content/pref-editing.xul)
+ content/editor/pref-composer.js (composer/content/pref-composer.js)
+ content/editor/pref-composer.xul (composer/content/pref-composer.xul)
+ content/editor/editorSmileyOverlay.xul (composer/content/editorSmileyOverlay.xul)
+ content/editor/editorPrefsOverlay.xul (composer/content/editorPrefsOverlay.xul)
+ content/editor/editorNavigatorOverlay.xul (composer/content/editorNavigatorOverlay.xul)
+ content/editor/editorMailOverlay.xul (composer/content/editorMailOverlay.xul)
+ content/editor/editorTasksOverlay.xul (composer/content/editorTasksOverlay.xul)
+ content/editor/editorApplicationOverlay.js (composer/content/editorApplicationOverlay.js)
+ content/editor/StructBarContextMenu.js (composer/content/StructBarContextMenu.js)
+ content/editor/images/sendtoback.gif (composer/content/images/sendtoback.gif)
+ content/editor/images/sendtoback-disabled.gif (composer/content/images/sendtoback-disabled.gif)
+ content/editor/images/bringtofront.gif (composer/content/images/bringtofront.gif)
+ content/editor/images/bringtofront-disabled.gif (composer/content/images/bringtofront-disabled.gif)
+ content/editor/images/tag-anchor.gif (composer/content/images/tag-anchor.gif)
+ content/editor/images/tag-abr.gif (composer/content/images/tag-abr.gif)
+ content/editor/images/tag-acr.gif (composer/content/images/tag-acr.gif)
+ content/editor/images/tag-adr.gif (composer/content/images/tag-adr.gif)
+ content/editor/images/tag-ara.gif (composer/content/images/tag-ara.gif)
+ content/editor/images/tag-bas.gif (composer/content/images/tag-bas.gif)
+ content/editor/images/tag-blq.gif (composer/content/images/tag-blq.gif)
+ content/editor/images/tag-bsf.gif (composer/content/images/tag-bsf.gif)
+ content/editor/images/tag-btn.gif (composer/content/images/tag-btn.gif)
+ content/editor/images/tag-cit.gif (composer/content/images/tag-cit.gif)
+ content/editor/images/tag-clg.gif (composer/content/images/tag-clg.gif)
+ content/editor/images/tag-cod.gif (composer/content/images/tag-cod.gif)
+ content/editor/images/tag-cpt.gif (composer/content/images/tag-cpt.gif)
+ content/editor/images/tag-ctr.gif (composer/content/images/tag-ctr.gif)
+ content/editor/images/tag-fld.gif (composer/content/images/tag-fld.gif)
+ content/editor/images/tag-fnt.gif (composer/content/images/tag-fnt.gif)
+ content/editor/images/tag-for.gif (composer/content/images/tag-for.gif)
+ content/editor/images/tag-frm.gif (composer/content/images/tag-frm.gif)
+ content/editor/images/tag-fst.gif (composer/content/images/tag-fst.gif)
+ content/editor/images/tag-ifr.gif (composer/content/images/tag-ifr.gif)
+ content/editor/images/tag-inp.gif (composer/content/images/tag-inp.gif)
+ content/editor/images/tag-lbl.gif (composer/content/images/tag-lbl.gif)
+ content/editor/images/tag-lgn.gif (composer/content/images/tag-lgn.gif)
+ content/editor/images/tag-lnk.gif (composer/content/images/tag-lnk.gif)
+ content/editor/images/tag-lst.gif (composer/content/images/tag-lst.gif)
+ content/editor/images/tag-men.gif (composer/content/images/tag-men.gif)
+ content/editor/images/tag-nbr.gif (composer/content/images/tag-nbr.gif)
+ content/editor/images/tag-nfr.gif (composer/content/images/tag-nfr.gif)
+ content/editor/images/tag-nsc.gif (composer/content/images/tag-nsc.gif)
+ content/editor/images/tag-opg.gif (composer/content/images/tag-opg.gif)
+ content/editor/images/tag-opt.gif (composer/content/images/tag-opt.gif)
+ content/editor/images/tag-prm.gif (composer/content/images/tag-prm.gif)
+ content/editor/images/tag-scr.gif (composer/content/images/tag-scr.gif)
+ content/editor/images/tag-slc.gif (composer/content/images/tag-slc.gif)
+ content/editor/images/tag-sml.gif (composer/content/images/tag-sml.gif)
+ content/editor/images/tag-smp.gif (composer/content/images/tag-smp.gif)
+ content/editor/images/tag-spn.gif (composer/content/images/tag-spn.gif)
+ content/editor/images/tag-stk.gif (composer/content/images/tag-stk.gif)
+ content/editor/images/tag-stl.gif (composer/content/images/tag-stl.gif)
+ content/editor/images/tag-stn.gif (composer/content/images/tag-stn.gif)
+ content/editor/images/tag-tbd.gif (composer/content/images/tag-tbd.gif)
+ content/editor/images/tag-tbl.gif (composer/content/images/tag-tbl.gif)
+ content/editor/images/tag-tft.gif (composer/content/images/tag-tft.gif)
+ content/editor/images/tag-thd.gif (composer/content/images/tag-thd.gif)
+ content/editor/images/tag-hed.gif (composer/content/images/tag-hed.gif)
+ content/editor/images/tag-isx.gif (composer/content/images/tag-isx.gif)
+ content/editor/images/tag-met.gif (composer/content/images/tag-met.gif)
+ content/editor/images/tag-ttl.gif (composer/content/images/tag-ttl.gif)
+ content/editor/images/tag-pln.gif (composer/content/images/tag-pln.gif)
+ content/editor/images/tag-xmp.gif (composer/content/images/tag-xmp.gif)
+ content/editor/images/tag-txt.gif (composer/content/images/tag-txt.gif)
+ content/editor/images/tag-a.gif (composer/content/images/tag-a.gif)
+ content/editor/images/tag-app.gif (composer/content/images/tag-app.gif)
+ content/editor/images/tag-b.gif (composer/content/images/tag-b.gif)
+ content/editor/images/tag-bdo.gif (composer/content/images/tag-bdo.gif)
+ content/editor/images/tag-big.gif (composer/content/images/tag-big.gif)
+ content/editor/images/tag-body.gif (composer/content/images/tag-body.gif)
+ content/editor/images/tag-br.gif (composer/content/images/tag-br.gif)
+ content/editor/images/tag-col.gif (composer/content/images/tag-col.gif)
+ content/editor/images/tag-dd.gif (composer/content/images/tag-dd.gif)
+ content/editor/images/tag-del.gif (composer/content/images/tag-del.gif)
+ content/editor/images/tag-dfn.gif (composer/content/images/tag-dfn.gif)
+ content/editor/images/tag-dir.gif (composer/content/images/tag-dir.gif)
+ content/editor/images/tag-div.gif (composer/content/images/tag-div.gif)
+ content/editor/images/tag-dl.gif (composer/content/images/tag-dl.gif)
+ content/editor/images/tag-dt.gif (composer/content/images/tag-dt.gif)
+ content/editor/images/tag-em.gif (composer/content/images/tag-em.gif)
+ content/editor/images/tag-h1.gif (composer/content/images/tag-h1.gif)
+ content/editor/images/tag-h2.gif (composer/content/images/tag-h2.gif)
+ content/editor/images/tag-h3.gif (composer/content/images/tag-h3.gif)
+ content/editor/images/tag-h4.gif (composer/content/images/tag-h4.gif)
+ content/editor/images/tag-h5.gif (composer/content/images/tag-h5.gif)
+ content/editor/images/tag-h6.gif (composer/content/images/tag-h6.gif)
+ content/editor/images/tag-hr.gif (composer/content/images/tag-hr.gif)
+ content/editor/images/tag-html.gif (composer/content/images/tag-html.gif)
+ content/editor/images/tag-i.gif (composer/content/images/tag-i.gif)
+ content/editor/images/tag-img.gif (composer/content/images/tag-img.gif)
+ content/editor/images/tag-ins.gif (composer/content/images/tag-ins.gif)
+ content/editor/images/tag-kbd.gif (composer/content/images/tag-kbd.gif)
+ content/editor/images/tag-li.gif (composer/content/images/tag-li.gif)
+ content/editor/images/tag-map.gif (composer/content/images/tag-map.gif)
+ content/editor/images/tag-obj.gif (composer/content/images/tag-obj.gif)
+ content/editor/images/tag-ol.gif (composer/content/images/tag-ol.gif)
+ content/editor/images/tag-p.gif (composer/content/images/tag-p.gif)
+ content/editor/images/tag-pre.gif (composer/content/images/tag-pre.gif)
+ content/editor/images/tag-q.gif (composer/content/images/tag-q.gif)
+ content/editor/images/tag-s.gif (composer/content/images/tag-s.gif)
+ content/editor/images/tag-sub.gif (composer/content/images/tag-sub.gif)
+ content/editor/images/tag-sup.gif (composer/content/images/tag-sup.gif)
+ content/editor/images/tag-td.gif (composer/content/images/tag-td.gif)
+ content/editor/images/tag-th.gif (composer/content/images/tag-th.gif)
+ content/editor/images/tag-tr.gif (composer/content/images/tag-tr.gif)
+ content/editor/images/tag-tt.gif (composer/content/images/tag-tt.gif)
+ content/editor/images/tag-u.gif (composer/content/images/tag-u.gif)
+ content/editor/images/tag-ul.gif (composer/content/images/tag-ul.gif)
+ content/editor/images/tag-var.gif (composer/content/images/tag-var.gif)
+ content/editor/images/tag-userdefined.gif (composer/content/images/tag-userdefined.gif)
+ content/editor/EdDialogCommon.js (dialogs/content/EdDialogCommon.js)
+ content/editor/EdLinkProps.xul (dialogs/content/EdLinkProps.xul)
+ content/editor/EdLinkProps.js (dialogs/content/EdLinkProps.js)
+ content/editor/EdLinkChecker.xul (dialogs/content/EdLinkChecker.xul)
+ content/editor/EdLinkChecker.js (dialogs/content/EdLinkChecker.js)
+ content/editor/EdImageProps.xul (dialogs/content/EdImageProps.xul)
+ content/editor/EdImageProps.js (dialogs/content/EdImageProps.js)
+ content/editor/EdImageOverlay.xul (dialogs/content/EdImageOverlay.xul)
+ content/editor/EdImageOverlay.js (dialogs/content/EdImageOverlay.js)
+ content/editor/EdHLineProps.xul (dialogs/content/EdHLineProps.xul)
+ content/editor/EdHLineProps.js (dialogs/content/EdHLineProps.js)
+ content/editor/EdReplace.xul (dialogs/content/EdReplace.xul)
+ content/editor/EdReplace.js (dialogs/content/EdReplace.js)
+ content/editor/EdSnapToGrid.xul (dialogs/content/EdSnapToGrid.xul)
+ content/editor/EdSnapToGrid.js (dialogs/content/EdSnapToGrid.js)
+ content/editor/EdSpellCheck.xul (dialogs/content/EdSpellCheck.xul)
+ content/editor/EdSpellCheck.js (dialogs/content/EdSpellCheck.js)
+ content/editor/EdDictionary.xul (dialogs/content/EdDictionary.xul)
+ content/editor/EdDictionary.js (dialogs/content/EdDictionary.js)
+ content/editor/EdNamedAnchorProps.xul (dialogs/content/EdNamedAnchorProps.xul)
+ content/editor/EdNamedAnchorProps.js (dialogs/content/EdNamedAnchorProps.js)
+ content/editor/EdInsertTOC.xul (dialogs/content/EdInsertTOC.xul)
+ content/editor/EdInsertTOC.js (dialogs/content/EdInsertTOC.js)
+ content/editor/EdInsertTable.xul (dialogs/content/EdInsertTable.xul)
+ content/editor/EdInsertTable.js (dialogs/content/EdInsertTable.js)
+ content/editor/EdTableProps.xul (dialogs/content/EdTableProps.xul)
+ content/editor/EdTableProps.js (dialogs/content/EdTableProps.js)
+ content/editor/EdFormProps.xul (dialogs/content/EdFormProps.xul)
+ content/editor/EdFormProps.js (dialogs/content/EdFormProps.js)
+ content/editor/EdInputProps.xul (dialogs/content/EdInputProps.xul)
+ content/editor/EdInputProps.js (dialogs/content/EdInputProps.js)
+ content/editor/EdInputImage.xul (dialogs/content/EdInputImage.xul)
+ content/editor/EdInputImage.js (dialogs/content/EdInputImage.js)
+ content/editor/EdTextAreaProps.xul (dialogs/content/EdTextAreaProps.xul)
+ content/editor/EdTextAreaProps.js (dialogs/content/EdTextAreaProps.js)
+ content/editor/EdSelectProps.xul (dialogs/content/EdSelectProps.xul)
+ content/editor/EdSelectProps.js (dialogs/content/EdSelectProps.js)
+ content/editor/EdButtonProps.xul (dialogs/content/EdButtonProps.xul)
+ content/editor/EdButtonProps.js (dialogs/content/EdButtonProps.js)
+ content/editor/EdLabelProps.xul (dialogs/content/EdLabelProps.xul)
+ content/editor/EdLabelProps.js (dialogs/content/EdLabelProps.js)
+ content/editor/EdFieldSetProps.xul (dialogs/content/EdFieldSetProps.xul)
+ content/editor/EdFieldSetProps.js (dialogs/content/EdFieldSetProps.js)
+ content/editor/EdInsSrc.xul (dialogs/content/EdInsSrc.xul)
+ content/editor/EdInsSrc.js (dialogs/content/EdInsSrc.js)
+ content/editor/EdInsertChars.xul (dialogs/content/EdInsertChars.xul)
+ content/editor/EdInsertChars.js (dialogs/content/EdInsertChars.js)
+ content/editor/EdDialogOverlay.xul (dialogs/content/EdDialogOverlay.xul)
+ content/editor/EdAdvancedEdit.xul (dialogs/content/EdAdvancedEdit.xul)
+ content/editor/EdAdvancedEdit.js (dialogs/content/EdAdvancedEdit.js)
+ content/editor/EdListProps.xul (dialogs/content/EdListProps.xul)
+ content/editor/EdListProps.js (dialogs/content/EdListProps.js)
+ content/editor/EdPageProps.xul (dialogs/content/EdPageProps.xul)
+ content/editor/EdPageProps.js (dialogs/content/EdPageProps.js)
+ content/editor/EdColorProps.xul (dialogs/content/EdColorProps.xul)
+ content/editor/EdColorProps.js (dialogs/content/EdColorProps.js)
+ content/editor/EdColorPicker.xul (dialogs/content/EdColorPicker.xul)
+ content/editor/EdColorPicker.js (dialogs/content/EdColorPicker.js)
+ content/editor/EdAECSSAttributes.js (dialogs/content/EdAECSSAttributes.js)
+ content/editor/EdAEHTMLAttributes.js (dialogs/content/EdAEHTMLAttributes.js)
+ content/editor/EdAEJSEAttributes.js (dialogs/content/EdAEJSEAttributes.js)
+ content/editor/EdAEAttributes.js (dialogs/content/EdAEAttributes.js)
+ content/editor/EdImageMap.js (dialogs/content/EdImageMap.js)
+ content/editor/EdImageMap.xul (dialogs/content/EdImageMap.xul)
+ content/editor/EdImageMapHotSpot.js (dialogs/content/EdImageMapHotSpot.js)
+ content/editor/EdImageMapHotSpot.xul (dialogs/content/EdImageMapHotSpot.xul)
+ content/editor/EdImageMapShapes.js (dialogs/content/EdImageMapShapes.js)
+ content/editor/EdImageMapPage.html (dialogs/content/EdImageMapPage.html)
+ content/editor/EditConflict.xul (dialogs/content/EditConflict.xul)
+ content/editor/EditConflict.js (dialogs/content/EditConflict.js)
+ content/editor/EditorSaveAsCharset.xul (dialogs/content/EditorSaveAsCharset.xul)
+ content/editor/EditorSaveAsCharset.js (dialogs/content/EditorSaveAsCharset.js)
+ content/editor/EdConvertToTable.xul (dialogs/content/EdConvertToTable.xul)
+ content/editor/EdConvertToTable.js (dialogs/content/EdConvertToTable.js)
+ content/editor/EditorPublish.xul (dialogs/content/EditorPublish.xul)
+ content/editor/EditorPublish.js (dialogs/content/EditorPublish.js)
+ content/editor/EditorPublishSettings.xul (dialogs/content/EditorPublishSettings.xul)
+ content/editor/EditorPublishSettings.js (dialogs/content/EditorPublishSettings.js)
+ content/editor/EditorPublishOverlay.xul (dialogs/content/EditorPublishOverlay.xul)
+ content/editor/EditorPublishProgress.xul (dialogs/content/EditorPublishProgress.xul)
+ content/editor/EditorPublishProgress.js (dialogs/content/EditorPublishProgress.js)
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/Makefile.in
@@ -0,0 +1,47 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Mozilla Browser code.
+#
+# The Initial Developer of the Original Code is
+# Benjamin Smedberg <bsmedberg@covad.net>
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+relativesrcdir = editor/ui/locales
+
+include $(DEPTH)/config/autoconf.mk
+
+DEFINES += -DAB_CD=$(AB_CD)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editor.dtd
@@ -0,0 +1,66 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!-- LOCALIZATION NOTE (editorWindow.titlemodifier): DONT_TRANSLATE -->
+<!ENTITY editorWindow.titlemodifier "Composer">
+<!ENTITY editorWindow.titlemodifiermenuseparator " - ">
+
+<!-- Menu items: the . means that the menu item isn't implemented yet -->
+
+<!-- View menu items -->
+<!ENTITY viewMenu.label "View">
+<!ENTITY viewmenu.accesskey "v">
+<!ENTITY compositionToolbarCmd.label "Composition Toolbar">
+<!ENTITY compositiontb.accesskey "c">
+<!ENTITY formattingToolbarCmd.label "Format Toolbar">
+<!ENTITY formattingtb.accesskey "f">
+<!ENTITY editmodeToolbarCmd.label "Edit Mode Toolbar">
+<!ENTITY editmodetb.accesskey "E">
+
+<!-- Format menu items -->
+<!ENTITY formatMenu.label "Format">
+<!ENTITY formatmenu.accesskey "o">
+
+<!ENTITY helpMenu.label "Help">
+<!ENTITY aboutCmd.label ".About">
+
+<!-- Display Mode Toolbar -->
+<!ENTITY editMode.label "Edit Mode:">
+
+<!ENTITY statusText.label "Done loading page">
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editor.properties
@@ -0,0 +1,226 @@
+#
+# moved from content/
+#
+# LOCALIZATION NOTE FILE: embedded "\n" represent HTML breaks (<br>)
+# Don't translate embedded "\n".
+# Don't translate strings like this: %variable%
+# as they will be replaced using JavaScript
+#
+Yes=Yes
+No=No
+Save=Save
+DontSave=Don't Save
+More=More
+Fewer=Fewer
+Less=Less
+MoreAttributes=More Attributes
+FewerAttributes=Fewer Attributes
+MoreProperties=More Properties
+FewerProperties=Fewer Properties
+PropertiesAccessKey=P
+None=None
+none=none
+OpenHTMLFile=Open HTML File
+SelectImageFile=Select Image File
+SaveDocument=Save Page
+SaveDocumentAs=Save Page As
+ExportToText=Export to Text
+EditMode=Edit Mode
+Preview=Preview
+Publish=Publish
+PublishPage=Publish Page
+DontPublish=Don't Publish
+SavePassword=Use Password Manager to save this password
+CorrectSpelling=(correct spelling)
+NoSuggestedWords=(no suggested words)
+NoMisspelledWord=No misspelled words
+CheckSpellingDone=Completed spell checking.
+CheckSpelling=Check Spelling
+LoadingDone=Done loading page
+InputError=Error
+Alert=Alert
+CantEditFramesetMsg=Composer cannot edit HTML framesets, or pages with inline frames. For framesets, try editing the page for each frame separately. For pages with iframes, save a copy of the page and remove the <iframe> tag.
+CantEditMimeTypeMsg=This type of page can't be edited.
+CantEditDocumentMsg=This page can't be edited for an unknown reason.
+HTMLFiles=HTML Files
+IMGFiles=Image Files
+TextFiles=Text Files
+AllFiles=All Files
+BeforeClosing=before closing
+BeforePreview=before viewing in the browser
+BeforeValidate=before validating the document
+# LOCALIZATION NOTE (SaveFilePrompt, PublishPrompt): Don't translate %title% and %reason% (this is the reason for asking user to close, such as "before closing")
+SaveFilePrompt=Save changes to "%title%" %reason%?
+PublishPrompt=Save changes to "%title%" %reason%?
+SaveFileFailed=Saving file failed!
+
+# Publishing error strings:
+# LOCALIZATION NOTE Don't translate %dir% or %file% in the Publishing error strings:
+FileNotFound=%file% not found.
+SubdirDoesNotExist=The subdirectory "%dir%" doesn't exist on this site or the filename "%file%" is already in use by another subdirectory.
+FilenameIsSubdir=The filename "%file%" is already in use by another subdirectory.
+ServerNotAvailable=The server is not available. Check your connection and try again later.
+Offline=You are currently offline. Click the icon near the lower-right corner of any window to go online.
+DiskFull=There is not enough disk space available to save the file "%file%."
+NameTooLong=The filename or subdirectory name is too long.
+AccessDenied=You do not have permission to publish to this location.
+UnknownPublishError=Unknown publishing error occurred.
+PublishFailed=Publishing failed.
+PublishCompleted=Publishing completed.
+AllFilesPublished=All files published
+# LOCALIZATION NOTE Don't translate %x% or %total%
+FailedFileMsg=%x% of %total% files failed to publish.
+# End-Publishing error strings
+Prompt=Prompt
+# LOCALIZATION NOTE (PromptFTPUsernamePassword): Don't translate %host%
+PromptFTPUsernamePassword=Enter username and password for FTP server at %host%
+RevertCaption=Revert To Last Saved
+Revert=Revert
+SendPageReason=before sending this page
+Send=Send
+## LOCALIZATION NOTE (PublishProgressCaption, PublishToSite, AbandonChanges): Don't translate %title%
+PublishProgressCaption=Publishing: %title%
+PublishToSite=Publishing to Site: %title%
+AbandonChanges=Abandon unsaved changes to "%title%" and reload page?
+DocumentTitle=Page Title
+NeedDocTitle=Please enter a title for the current page.
+DocTitleHelp=This identifies the page in the window title and bookmarks.
+CancelPublishTitle=Cancel publishing?
+## LOCALIZATION NOTE: "Continue" in this sentence must match the text for
+## the CancelPublishContinue key below
+CancelPublishMessage=Cancelling while publishing is in progress may result in your file(s) being incompletely transferred. Would you like to Continue or Cancel?
+CancelPublishContinue=Continue
+AttributesFor=Current attributes for:
+MissingImageError=Please enter or choose an image of type gif, jpg, or png.
+EmptyHREFError=Please choose a location to create a new link.
+LinkText=Link Text
+LinkImage=Link Image
+MixedSelection=[Mixed selection]
+Mixed=(mixed)
+EnterLinkText=Enter text to display for the link:
+EnterLinkTextAccessKey=T
+EmptyLinkTextError=Please enter some text for this link.
+EditTextWarning=This will replace existing content.
+#LOCALIZATION NOTE (ValidateNumber):Don't translate: %n% %min% %max%
+ValidateRangeMsg=The number you entered (%n%) is outside of the allowed range.
+ValidateNumberMsg=Please enter a number between %min% and %max%.
+MissingAnchorNameError=Please enter a name for this anchor.
+#LOCALIZATION NOTE (DuplicateAnchorNameError): Don't translate %name%
+DuplicateAnchorNameError="%name%" already exists in this page. Please enter a different name.
+BulletStyle=Bullet Style
+SolidCircle=Solid circle
+OpenCircle=Open circle
+SolidSquare=Solid square
+NumberStyle=Number Style
+Automatic=Automatic
+Style_1=1, 2, 3…
+Style_I=I, II, III…
+Style_i=i, ii, iii…
+Style_A=A, B, C…
+Style_a=a, b, c…
+Pixels=pixels
+Percent=percent
+PercentOfCell=% of cell
+PercentOfWindow=% of window
+PercentOfTable=% of table
+untitled=untitled
+ShowToolbar=Show Toolbar
+HideToolbar=Hide Toolbar
+ImapError=Unable to load image
+ImapCheck=\nPlease select a new location (URL) and try again.
+SaveToUseRelativeUrl=Relative URLs can only be used on pages which have been saved
+NoNamedAnchorsOrHeadings=(No named anchors or headings in this page)
+TextColor=Text Color
+HighlightColor=Highlight Color
+PageColor=Page Background Color
+BlockColor=Block Background Color
+TableColor=Table Background Color
+CellColor=Cell Background Color
+TableOrCellColor=Table or Cell Color
+LinkColor=Link Text Color
+ActiveLinkColor=Active Link Color
+VisitedLinkColor=Visited Link Color
+NoColorError=Click on a color or enter a valid HTML color string
+Table=Table
+TableCell=Table Cell
+NestedTable=Nested Table
+HLine=Horizontal Line
+Link=Link
+Image=Image
+ImageAndLink=Image and Link
+NamedAnchor=Named Anchor
+List=List
+ListItem=List Item
+Form=Form
+InputTag=Form Field
+InputImage=Form Image
+TextArea=Text Area
+Select=Selection List
+Button=Button
+Label=Label
+FieldSet=Field Set
+Tag=Tag
+MissingSiteNameError=Please enter a name for this publishing site.
+MissingPublishUrlError=Please enter a location for publishing this page.
+MissingPublishFilename=Please enter a filename for the current page.
+MissingPublishSiteError=No publishing site information given. Switching to Settings panel so you can supply publishing information.
+#LOCALIZATION NOTE (DuplicateSiteNameError): Don't translate %name%
+DuplicateSiteNameError="%name%" already exists. Please enter a different site name.
+AdvancedProperties=Advanced Properties…
+AdvancedEditForCellMsg=Advanced Edit is unavailable when multiple cells are selected
+# LOCALIZATION NOTE (ObjectProperties):Don't translate "%obj%" it will be replaced with one of above object nouns
+ObjectProperties=%obj% Properties…
+# LOCALIZATION NOTE This character must be in the above string and not confict with other accesskeys in Format menu
+ObjectPropertiesAccessKey=o
+# LOCALIZATION NOTE (JoinSelectedCells): This variable should contain the "tablejoincells.accesskey"
+# letter as defined in editorOverlay.dtd
+JoinSelectedCells=Join Selected Cells
+# LOCALIZATION NOTE (JoinCellToRight): This variable should contain the "tablejoincells.accesskey"
+# letter as defined in editorOverlay.dtd
+JoinCellToRight=Join with Cell to the Right
+JoinCellAccesskey=j
+# LOCALIZATION NOTE (TableSelectKey): DONT_TRANSLATE
+TableSelectKey=Ctrl+
+# LOCALIZATION NOTE (XulKeyDefault): DONT_TRANSLATE
+XulKeyDefault=Ctrl+
+# LOCALIZATION NOTE (XulKeyMac): DONT_TRANSLATE
+XulKeyMac=Cmd+
+# LOCALIZATION NOTE (XulKeyUnix): DONT_TRANSLATE
+XulKeyUnix=Alt+
+# LOCALIZATION NOTE (Del): DONT_TRANSLATE
+Del=Del
+Delete=Delete
+DeleteCells=Delete Cells
+DeleteTableTitle=Delete Rows or Columns
+DeleteTableMsg=Reducing the number of rows or columns will delete table cells and their contents. Do you really want to do this?
+Clear=Clear
+#Mouse actions
+Click=Click
+Drag=Drag
+Unknown=Unknown
+#
+# LOCALIZATION NOTE "RemoveTextStylesAccesskey" is used for both
+# menu items: "RemoveTextStyles" and "StopTextStyles"
+RemoveTextStylesAccesskey=x
+RemoveTextStyles=Remove All Text Styles
+StopTextStyles=Discontinue Text Styles
+#
+# LOCALIZATION NOTE "RemoveLinksAccesskey" is used for both
+# menu items: "RemoveLinks" and "StopLinks"
+RemoveLinksAccesskey=n
+RemoveLinks=Remove Links
+StopLinks=Discontinue Link
+#
+NoFormAction=It is recommended that you enter an action for this form. Self-posting forms are an advanced technique that may not work consistently in all browsers.
+NoAltText=If the image is relevant to the content of the document, you must supply alternate text that will appear in text-only browsers, and that will appear in other browsers when an image is loading or when image loading is disabled.
+SaveImageAs=Save Image (%NAME%)…
+NoSeparatorCharacter=Please enter a single character to use for separating into columns
+#
+# LOCALIZATION NOTE please do not translate %brand%, it will be used programmatically
+# download spelling dictionaries confirmation dialog
+DictDownldConfirmTit=Download Dictionaries
+DictDownldConfirmMsg=%brand% will close the current window and redirect you to a spellchecker download site.
+#
+NoHeadTag=The HTML source could not be converted back into the document because the required <head> tag is missing. Please add it.
+NoBodyTag=The HTML source could not be converted back into the document because the required <body> tag is missing. Please add it.
+NoLinksToCheck=There are no elements with links to check
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editorNavigatorOverlay.dtd
@@ -0,0 +1,7 @@
+
+<!ENTITY editPageCmd.label "Edit Page in Composer">
+<!ENTITY editPageCmd.accesskey "e">
+
+<!ENTITY editLinkCmd.label "Edit Link in Composer">
+<!ENTITY editLinkCmd.accesskey "E">
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editorOverlay.dtd
@@ -0,0 +1,592 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1999-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Sammy Ford
+ - Blake Ross
+ - Ryan Cassin (rcassin@supernova.org)
+ - Daniel Glazman (glazman@netscape.com)
+ - Stephen Donner (technutz@netscape.net)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Attn: Localization - some of the menus in this dialog directly affect mail also. -->
+
+<!-- File menu items -->
+<!ENTITY fileMenu.label "File">
+<!ENTITY filemenu.accesskey "f">
+<!ENTITY newBlankPageCmd.label "Composer Page">
+<!ENTITY newBlankPage.accesskey "P" >
+<!ENTITY newMenu.label "New">
+<!ENTITY openFileCmd.label "Open File…">
+<!ENTITY fileopen.accesskey "o">
+<!ENTITY fileopen.keybinding "o">
+<!ENTITY openremoteCmd.label "Open Web Location…">
+<!ENTITY fileopenremote.accesskey "l">
+<!ENTITY fileopenremote.keybinding "l">
+<!ENTITY fileRecentMenu.label "Recent Pages">
+<!ENTITY filerecentmenu.accesskey "r">
+<!ENTITY fileRevert.label "Revert">
+<!ENTITY filerevert.accesskey "v">
+<!ENTITY saveCmd.label "Save">
+<!ENTITY filesave.accesskey "s">
+<!ENTITY filesave.keybinding "s">
+<!ENTITY saveAsCmd.label "Save As…">
+<!ENTITY filesaveas.accesskey "A">
+
+<!ENTITY publishCmd.label "Publish">
+<!ENTITY publishcmd.accesskey "b">
+<!ENTITY publishAsCmd.label "Publish As…">
+<!ENTITY publishas.accesskey "h">
+<!ENTITY exportToTextCmd.label "Export to Text…">
+<!ENTITY fileexporttotext.accesskey "T">
+<!ENTITY saveAsChangeEncodingCmd.label "Save And Change Character Encoding">
+<!ENTITY filesaveandchangeencoding.accesskey "E">
+<!ENTITY previewCmd.label "Browse Page">
+<!ENTITY filepreview.accesskey "w">
+<!ENTITY sendPageCmd.label "Send Page…">
+<!ENTITY sendPage.accesskey "d">
+<!ENTITY printSetupCmd.label "Page Setup…">
+<!ENTITY fileprintsetup.accesskey "u">
+<!ENTITY printPreviewCmd.label "Print Preview">
+<!ENTITY fileprintpreview.accesskey "v">
+<!ENTITY printCmd.label "Print…">
+<!ENTITY printButtonCmd.label "Print…">
+<!ENTITY fileprint.accesskey "p">
+<!ENTITY fileprint.keybinding "p">
+<!ENTITY closeCmd.label "Close">
+<!ENTITY fileclose.accesskey "c">
+<!ENTITY fileclose.keybinding "w">
+<!ENTITY exitCmd.label "Quit">
+<!ENTITY fileexit.accesskey "q">
+<!ENTITY fileexit.keybinding "q">
+
+<!-- Edit menu items -->
+<!ENTITY editMenu.label "Edit">
+<!ENTITY editmenu.accesskey "e">
+<!ENTITY pasteNoFormatting.label "Paste Without Formatting">
+<!ENTITY pasteNoFormatting.accesskey "o">
+<!ENTITY pasteAs.label "Paste As">
+<!ENTITY pasteAs.accesskey "a">
+<!ENTITY publishSettings.label "Publishing Site Settings…">
+<!ENTITY publishSettings.accesskey "b">
+
+<!-- For a "Paste" submenu when more than 1
+ clipboard formats are available -->
+<!ENTITY pasteHTMLCmd.label "HTML">
+<!ENTITY pasteHTML.accesskey "h">
+<!ENTITY pasteTextCmd.label "Text">
+<!ENTITY pasteText.accesskey "t">
+<!ENTITY pasteImageCmd.label "Image">
+<!ENTITY pasteImage.accesskey "i">
+<!ENTITY pasteRowsCmd.label "Rows">
+<!ENTITY pasteRows.accesskey "r">
+<!ENTITY pasteColumnsCmd.label "Columns">
+<!ENTITY pasteColumns.accesskey "c">
+<!-- LOCALIZATION NOTE: Text for menu item is in editor.properties
+ Set to: "Table" or "Nested Table" depending on context
+ This accesskey must be in both strings -->
+<!ENTITY pasteTable.accesskey "a">
+<!ENTITY pasteLinkCmd.label "Link">
+<!ENTITY editpastelink.accesskey "l">
+<!ENTITY pasteAsQuotationCmd.label "Paste As Quotation">
+<!ENTITY editpastequotation.accesskey "q">
+<!ENTITY editpastequotation.keybinding "v">
+<!ENTITY editStripQuotesCmd.label "Strip Quotes">
+<!ENTITY editRewrapCmd.label "Rewrap">
+<!ENTITY findCmd.label "Find and Replace…">
+<!ENTITY editfind.accesskey "f">
+<!ENTITY editfind.keybinding "f">
+<!ENTITY editfind.keybinding2 "VK_F19">
+<!ENTITY findAgainCmd.label "Find Again">
+<!ENTITY editfindnext.accesskey "g">
+<!ENTITY editfindnext.keybinding "g">
+<!ENTITY editfindnext.keybinding2 "VK_F3">
+<!ENTITY findPrevCmd.label "Find Previous">
+<!ENTITY editfindprev.accesskey "v">
+<!ENTITY editfindprev.keybinding "g">
+<!ENTITY editfindprev.keybinding2 "VK_F3">
+<!ENTITY enableInlineSpellChecker.label "Spellcheck As You Type">
+<!ENTITY enableInlineSpellChecker.accesskey "S">
+<!ENTITY checkSpellingCmd.label "Check Spelling">
+<!ENTITY editcheckspelling.accesskey "h">
+<!ENTITY editcheckspelling.keybinding "k">
+<!ENTITY validateCmd.label "Validate HTML">
+<!ENTITY validate.accesskey "v">
+<!ENTITY checkLinksCmd.label "Check Links">
+
+<!-- View menu items -->
+<!ENTITY viewPageSource.label "Page Source">
+<!ENTITY viewpagesource.accesskey "s">
+<!ENTITY viewParagraphMarks.label "Paragraph Marks">
+<!ENTITY viewparagraphmarks.accesskey "p">
+
+<!-- Insert menu items -->
+<!ENTITY insertMenu.label "Insert">
+<!ENTITY insertmenu.accesskey "i">
+<!ENTITY insertLinkCmd.label "Link…">
+<!ENTITY insertlink.accesskey "l">
+<!ENTITY insertlink.keybinding "l">
+<!ENTITY insertAnchorCmd.label "Named Anchor…">
+<!ENTITY insertanchor.accesskey "A">
+<!ENTITY insertImageCmd.label "Image…">
+<!ENTITY insertimage.accesskey "i">
+<!ENTITY insertImageMapCmd.label "Image Map…">
+<!ENTITY insertHLineCmd.label "Horizontal Line">
+<!ENTITY inserthline.accesskey "o">
+<!ENTITY insertTableCmd.label "Table…">
+<!ENTITY inserttable.accesskey "t">
+<!ENTITY insertFormMenu.label "Form">
+<!ENTITY insertformmenu.accesskey "F">
+<!ENTITY insertHTMLCmd.label "HTML…">
+<!ENTITY insertHTMLCmd.accesskey "h">
+<!ENTITY insertCharsCmd.label "Characters and Symbols…">
+<!ENTITY insertchars.accesskey "C">
+<!ENTITY insertBreakCmd.label "Line Break">
+<!ENTITY insertbreak.accesskey "b">
+<!ENTITY insertBreakAllCmd.label "Break Below Image(s)">
+<!ENTITY insertbreakall.accesskey "k">
+
+<!-- Insert form menu items -->
+<!ENTITY insertFormCmd.label "Define Form…">
+<!ENTITY insertform.accesskey "D">
+<!ENTITY insertInputTagCmd.label "Form Field…">
+<!ENTITY insertinputtag.accesskey "e">
+<!ENTITY insertInputImageCmd.label "Form Image…">
+<!ENTITY insertinputimage.accesskey "I">
+<!ENTITY insertTextAreaCmd.label "Text Area…">
+<!ENTITY inserttextarea.accesskey "T">
+<!ENTITY insertSelectCmd.label "Selection List…">
+<!ENTITY insertselect.accesskey "S">
+<!ENTITY insertButtonCmd.label "Define Button…">
+<!ENTITY insertbutton.accesskey "B">
+<!ENTITY insertLabelCmd.label "Define Label">
+<!ENTITY insertlabel.accesskey "L">
+<!ENTITY insertFieldSetCmd.label "Define Field Set…">
+<!ENTITY insertfieldset.accesskey "F">
+<!ENTITY insertIsIndexCmd.label "Index Search">
+<!ENTITY insertisindex.accesskey "x">
+
+<!-- Used just in context popup. -->
+<!ENTITY spellCheckNoSuggestions.label "(No Suggestions Found)">
+<!ENTITY spellCheckIgnoreWord.label "Ignore Word">
+<!ENTITY spellCheckIgnoreWord.accesskey "I">
+<!ENTITY spellCheckAddToDictionary.label "Add to Dictionary">
+<!ENTITY spellCheckAddToDictionary.accesskey "n">
+<!ENTITY createLinkCmd.label "Create Link…">
+<!ENTITY createlink.accesskey "k">
+<!ENTITY editLinkCmd.label "Edit Link in New Composer">
+<!ENTITY editlink.accesskey "i">
+<!-- (Toplevel Edit menu uses utilityOverlay) -->
+<!ENTITY undoCmd.label "Undo">
+<!ENTITY undo.accesskey "u">
+<!ENTITY redoCmd.label "Redo">
+<!ENTITY redo.accesskey "r">
+<!ENTITY cutCmd.label "Cut">
+<!ENTITY cut.accesskey "t">
+<!ENTITY copyCmd.label "Copy">
+<!ENTITY copy.accesskey "c">
+<!ENTITY pasteCmd.label "Paste">
+<!ENTITY paste.accesskey "p">
+<!ENTITY deleteCmd.label "Delete">
+<!ENTITY delete.accesskey "d">
+<!ENTITY clearCmd.label "Clear">
+<!ENTITY clear.accesskey "l">
+<!ENTITY selectAllCmd.label "Select All">
+<!ENTITY selectall.accesskey "a">
+
+<!-- Font Face SubMenu -->
+<!ENTITY FontFaceSelect.tooltip "Choose a font">
+<!ENTITY fontfaceMenu.label "Font">
+<!ENTITY formatfontmenu.accesskey "f">
+<!ENTITY fontVarWidth.label "Variable Width">
+<!ENTITY fontvarwidth.accesskey "v">
+<!ENTITY fontFixedWidth.label "Fixed Width">
+<!ENTITY fontfixedwidth.accesskey "x">
+<!ENTITY formatfontfixed.keybinding "t">
+<!ENTITY fontHelveticaFont.label "Helvetica, Arial">
+<!ENTITY fonthelvetica.accesskey "l">
+<!ENTITY fontTimes.label "Times">
+<!ENTITY fonttimes.accesskey "t">
+<!ENTITY fontCourier.label "Courier">
+<!ENTITY fontcourier.accesskey "c">
+<!ENTITY localfontfaceMenu.label "Local Fonts">
+<!ENTITY localfontmenu.accesskey "f">
+
+<!-- Font Size SubMenu -->
+<!ENTITY FontSizeSelect.tooltip "Choose a font size">
+<!ENTITY decreaseFontSize.label "Smaller">
+<!ENTITY decreasefontsize.accesskey "r">
+<!ENTITY decreaseFontSize.keybinding "-">
+<!ENTITY increaseFontSize.label "Larger">
+<!ENTITY increasefontsize.accesskey "g">
+<!ENTITY increaseFontSize.keybinding "+">
+<!ENTITY increaseFontSize.keybinding2 "="> <!-- + is above this key on many keyboards -->
+
+<!ENTITY fontsizeMenu.label "Size">
+<!ENTITY formatsizemenu.accesskey "z">
+<!ENTITY size-xx-smallCmd.label "xx-small">
+<!ENTITY size-xx-small.accesskey "a">
+<!ENTITY size-x-smallCmd.label "x-small">
+<!ENTITY size-x-small.accesskey "m">
+<!ENTITY size-smallCmd.label "small">
+<!ENTITY size-small.accesskey "s">
+<!ENTITY size-mediumCmd.label "medium">
+<!ENTITY size-medium.accesskey "d">
+<!ENTITY size-largeCmd.label "large">
+<!ENTITY size-large.accesskey "l">
+<!ENTITY size-x-largeCmd.label "x-large">
+<!ENTITY size-x-large.accesskey "x">
+<!ENTITY size-xx-largeCmd.label "xx-large">
+<!ENTITY size-xx-large.accesskey "e">
+
+<!-- Font Style SubMenu -->
+<!ENTITY fontStyleMenu.label "Text Style">
+<!ENTITY formatstylemenu.accesskey "s">
+<!ENTITY styleBoldCmd.label "Bold">
+<!ENTITY stylebold.accesskey "b">
+<!ENTITY stylebold.keybinding "b">
+<!ENTITY styleItalicCmd.label "Italic">
+<!ENTITY styleitalic.accesskey "I">
+<!ENTITY styleitalic.keybinding "i">
+<!ENTITY styleUnderlineCmd.label "Underline">
+<!ENTITY styleunderline.accesskey "u">
+<!ENTITY styleunderline.keybinding "u">
+<!ENTITY styleStrikeThruCmd.label "Strikethrough">
+<!ENTITY stylestrikethru.accesskey "k">
+<!ENTITY styleSuperscriptCmd.label "Superscript">
+<!ENTITY stylesuperscript.accesskey "p">
+<!ENTITY styleSubscriptCmd.label "Subscript">
+<!ENTITY stylesubscript.accesskey "S">
+<!ENTITY styleNonbreakingCmd.label "Nonbreaking">
+<!ENTITY stylenonbreaking.accesskey "N">
+<!ENTITY styleEm.label "Emphasis">
+<!ENTITY styleEm.accesskey "e">
+<!ENTITY styleStrong.label "Stronger Emphasis">
+<!ENTITY styleStrong.accesskey "t">
+<!ENTITY styleCite.label "Citation">
+<!ENTITY styleCite.accesskey "c">
+<!ENTITY styleAbbr.label "Abbreviation">
+<!ENTITY styleAbbr.accesskey "A">
+<!ENTITY styleAcronym.label "Acronym">
+<!ENTITY styleAcronym.accesskey "r">
+<!ENTITY styleCode.label "Code">
+<!ENTITY styleCode.accesskey "o">
+<!ENTITY styleSamp.label "Sample Output">
+<!ENTITY styleSamp.accesskey "m">
+<!ENTITY styleVar.label "Variable">
+<!ENTITY styleVar.accesskey "v">
+
+<!ENTITY formatFontColor.label "Text Color…">
+<!ENTITY formatfontcolor.accesskey "c">
+<!ENTITY tableOrCellColor.label "Table or Cell Background Color…">
+<!ENTITY tableOrCellColor.accesskey "B">
+
+<!ENTITY formatremovestyles.keybinding "y">
+<!ENTITY formatremovelinks.keybinding "k">
+<!ENTITY formatRemoveNamedAnchors.label "Remove Named Anchors">
+<!ENTITY formatRemoveNamedAnchors.accesskey "R">
+<!ENTITY formatremovenamedanchors.keybinding "a">
+
+<!ENTITY formatindent.keybinding "]">
+<!ENTITY formatoutdent.keybinding "[">
+<!ENTITY paragraphMenu.label "Paragraph">
+<!ENTITY formatparagraphmenu.accesskey "P">
+<!ENTITY paragraphParagraphCmd.label "Paragraph">
+<!ENTITY paragraphparagraph.accesskey "P">
+<!ENTITY heading1Cmd.label "Heading 1">
+<!ENTITY heading1.accesskey "1">
+<!ENTITY heading2Cmd.label "Heading 2">
+<!ENTITY heading2.accesskey "2">
+<!ENTITY heading3Cmd.label "Heading 3">
+<!ENTITY heading3.accesskey "3">
+<!ENTITY heading4Cmd.label "Heading 4">
+<!ENTITY heading4.accesskey "4">
+<!ENTITY heading5Cmd.label "Heading 5">
+<!ENTITY heading5.accesskey "5">
+<!ENTITY heading6Cmd.label "Heading 6">
+<!ENTITY heading6.accesskey "6">
+<!ENTITY paragraphAddressCmd.label "Address">
+<!ENTITY paragraphaddress.accesskey "a">
+<!ENTITY paragraphPreformatCmd.label "Preformat">
+<!ENTITY paragraphpreformat.accesskey "f">
+<!ENTITY paragraphBlockquoteCmd.label "Blockquote">
+<!ENTITY paragraphblockquote.accesskey "b">
+
+<!-- List menu items -->
+<!ENTITY formatlistMenu.label "List">
+<!ENTITY formatlistmenu.accesskey "l">
+<!ENTITY noneCmd.label "None">
+<!ENTITY none.accesskey "N">
+<!ENTITY listBulletCmd.label "Bulleted">
+<!ENTITY listbullet.accesskey "b">
+<!ENTITY listNumberedCmd.label "Numbered">
+<!ENTITY listnumbered.accesskey "m">
+<!ENTITY listTermCmd.label "Term">
+<!ENTITY listterm.accesskey "t">
+<!ENTITY listDefinitionCmd.label "Definition">
+<!ENTITY listdefinition.accesskey "d">
+<!ENTITY listProps.label "List Properties…">
+<!ENTITY listprops.accesskey "l">
+
+<!ENTITY ParagraphSelect.tooltip "Choose a paragraph format">
+<!-- Shared in Paragraph, and Toolbar menulist -->
+<!ENTITY bodyTextCmd.label "Body Text">
+<!ENTITY bodytext.accesskey "T">
+<!-- isn't used in menu now, but may be added in future -->
+<!ENTITY advancedPropertiesCmd.label "Advanced Properties">
+<!ENTITY advancedproperties.accesskey "v">
+
+<!ENTITY NormalAbbr.label "Text">
+<!ENTITY ParagraphAbbr.label "P">
+<!ENTITY Heading1Abbr.label "H1">
+<!ENTITY Heading2Abbr.label "H2">
+<!ENTITY Heading3Abbr.label "H3">
+<!ENTITY Heading4Abbr.label "H4">
+<!ENTITY Heading5Abbr.label "H5">
+<!ENTITY Heading6Abbr.label "H6">
+<!ENTITY BlockquoteAbbr.label "BQ">
+<!ENTITY AddressAbbr.label "Addr.">
+<!ENTITY PreformatAbbr.label "Pre.">
+
+<!-- Style Sheet submenu NOT IMPLEMENTED -->
+<!ENTITY stylesheetMenu.label "Apply Style Sheet">
+<!ENTITY formatstylesheetmenu.accesskey "y">
+
+<!-- Align menu items -->
+<!ENTITY alignMenu.label "Align">
+<!ENTITY formatalignmenu.accesskey "a">
+<!ENTITY alignLeft.label "Left">
+<!ENTITY alignleft.accesskey "l">
+<!ENTITY alignLeft.tooltip "Align Left">
+<!ENTITY alignCenter.label "Center">
+<!ENTITY aligncenter.accesskey "c">
+<!ENTITY alignCenter.tooltip "Align Center">
+<!ENTITY alignRight.label "Right">
+<!ENTITY alignright.accesskey "r">
+<!ENTITY alignRight.tooltip "Align Right">
+<!ENTITY alignJustify.label "Justify">
+<!ENTITY alignjustify.accesskey "j">
+<!ENTITY alignJustify.tooltip "Align Justified">
+
+<!-- Layer toolbar items -->
+<!ENTITY layer.tooltip "Layer">
+<!ENTITY layerSendToBack.tooltip "Send to Back">
+<!ENTITY layerBringToFront.tooltip "Bring to Front">
+
+<!ENTITY increaseIndent.label "Increase Indent">
+<!ENTITY increaseindent.accesskey "i">
+<!ENTITY increaseindentkb "=">
+<!ENTITY decreaseIndent.label "Decrease Indent">
+<!ENTITY decreaseindent.accesskey "D">
+<!ENTITY decreaseindentkb "-">
+
+<!ENTITY grid.label "Positioning grid">
+<!ENTITY grid.accesskey "t">
+
+<!ENTITY pageProperties.label "Page Title and Properties…">
+<!ENTITY pageproperties.accesskey "g">
+<!ENTITY colorsAndBackground.label "Page Colors and Background…">
+<!ENTITY colorsandbackground.accesskey "u">
+
+<!-- Table Menu -->
+<!ENTITY tableMenu.label "Table">
+<!ENTITY tablemenu.accesskey "b">
+<!-- Select Submenu -->
+<!ENTITY tableSelectMenu.label "Select">
+<!ENTITY tableselectmenu.accesskey "s">
+
+<!ENTITY tableSelectMenu2.label "Table Select">
+<!ENTITY tableInsertMenu2.label "Table Insert">
+<!ENTITY tableDeleteMenu2.label "Table Delete">
+
+<!-- Insert SubMenu -->
+<!ENTITY tableInsertMenu.label "Insert">
+<!ENTITY tableinsertmenu.accesskey "i">
+<!ENTITY tableTable.label "Table">
+<!ENTITY tabletable.accesskey "t">
+<!ENTITY tableRow.label "Row">
+<!ENTITY tableRows.label "Row(s)">
+<!ENTITY tablerow.accesskey "r">
+<!ENTITY tableRowAbove.label "Row Above">
+<!-- uses tablerow.accesskey -->
+<!ENTITY tableRowBelow.label "Row Below">
+<!ENTITY tablerowbelow.accesskey "b">
+<!ENTITY tableColumn.label "Column">
+<!ENTITY tableColumns.label "Column(s)">
+<!ENTITY tablecolumn.accesskey "o">
+<!ENTITY tableColumnBefore.label "Column Before">
+<!-- uses tablecolumn.accesskey -->
+<!ENTITY tableColumnAfter.label "Column After">
+<!ENTITY tablecolumnafter.accesskey "a">
+<!ENTITY tableCell.label "Cell">
+<!ENTITY tableCells.label "Cell(s)">
+<!ENTITY tablecell.accesskey "c">
+<!ENTITY tableCellContents.label "Cell Contents">
+<!ENTITY tablecellcontents.accesskey "n">
+<!ENTITY tableAllCells.label "All Cells">
+<!ENTITY tableCellBefore.label "Cell Before">
+<!ENTITY tableallcells.accesskey "a">
+<!-- uses tablecell.accesskey -->
+<!ENTITY tableCellAfter.label "Cell After">
+<!ENTITY tablecellafter.accesskey "f">
+<!-- Delete SubMenu -->
+<!ENTITY tableDeleteMenu.label "Delete">
+<!ENTITY tabledeletemenu.accesskey "D">
+
+<!ENTITY tableFix.label "Fix Table Layout">
+<!ENTITY tablefix.accesskey "f">
+<!-- text for "Join Cells" is in editor.properties
+ ("JoinSelectedCells" and "JoinCellToRight")
+ the access key must exist in both of those strings
+ But value must be set here for accesskey to draw properly
+-->
+<!ENTITY tableJoinCells.label "j">
+<!ENTITY tablejoincells.accesskey "j">
+<!ENTITY tableSplitCell.label "Split Cell">
+<!ENTITY tablesplitcell.accesskey "c">
+<!ENTITY convertToTable.label "Create Table from Selection">
+<!ENTITY converttotable.accesskey "r">
+<!ENTITY tableProperties.label "Table Properties…">
+<!ENTITY tableProperties.accesskey "o">
+
+<!-- Tools menu -->
+<!ENTITY toolsmenu.accesskey "l">
+<!ENTITY toolbrowser.accesskey "b">
+<!ENTITY toolplaineditor.accesskey "p">
+<!ENTITY toolsetfocus.accesskey "f">
+
+<!-- Toolbar-only items -->
+<!ENTITY menuBar.tooltip "Menu Bar">
+<!ENTITY compositionToolbar.tooltip "Composition Toolbar">
+<!ENTITY formatToolbar.tooltip "Formatting Toolbar">
+<!ENTITY newToolbarCmd.tooltip "Create a new Composer page">
+<!ENTITY openToolbarCmd.label "Open">
+<!ENTITY openToolbarCmd.tooltip "Open a local file">
+<!ENTITY saveToolbarCmd.tooltip "Save file to a local location">
+<!ENTITY publishToolbarCmd.tooltip "Upload file to a remote location">
+<!ENTITY previewToolbarCmd.label "Browse">
+<!ENTITY previewToolbarCmd.tooltip "Load this page in the browser">
+<!ENTITY printToolbarCmd.label "Print">
+<!ENTITY printToolbarCmd.tooltip "Print this page">
+<!ENTITY findToolbarCmd.label "Find">
+<!ENTITY findToolbarCmd.tooltip "Find text in page">
+<!ENTITY spellToolbarCmd.label "Spell">
+<!ENTITY spellToolbarCmd.tooltip "Check spelling of selection or entire page">
+<!ENTITY imageToolbarCmd.label "Image">
+<!ENTITY imageToolbarCmd.tooltip "Insert new image or edit selected image's properties">
+<!ENTITY hruleToolbarCmd.label "H.Line">
+<!ENTITY hruleToolbarCmd.tooltip "Insert horizontal line or edit selected line's properties">
+<!ENTITY tableToolbarCmd.label "Table">
+<!ENTITY tableToolbarCmd.tooltip "Insert new table or edit selected table's properties">
+<!ENTITY linkToolbarCmd.label "Link">
+<!ENTITY linkToolbarCmd.tooltip "Insert new link or edit selected link's properties">
+<!ENTITY anchorToolbarCmd.label "Anchor">
+<!ENTITY anchorToolbarCmd.tooltip "Insert new named anchor or edit selected anchor's properties">
+<!ENTITY textColorCaption.label "Text Color">
+<!ENTITY TextColorButton.tooltip "Choose color for text">
+<!ENTITY BackgroundColorButton.tooltip "Choose color for background">
+<!ENTITY throbber.tooltip "Go to the &vendorShortName; home page">
+<!ENTITY HighlightColorButton.tooltip "Choose highlight color for text">
+
+<!-- Editor toolbar -->
+<!ENTITY decreaseFontSizeToolbarCmd.tooltip "Smaller font size">
+<!ENTITY increaseFontSizeToolbarCmd.tooltip "Larger font size">
+<!ENTITY boldToolbarCmd.tooltip "Bold">
+<!ENTITY italicToolbarCmd.tooltip "Italic">
+<!ENTITY underlineToolbarCmd.tooltip "Underline">
+<!ENTITY bulletListToolbarCmd.tooltip "Apply or remove bulleted list">
+<!ENTITY numberListToolbarCmd.tooltip "Apply or remove numbered list">
+<!ENTITY outdentToolbarCmd.tooltip "Outdent text (move left)">
+<!ENTITY indentToolbarCmd.tooltip "Indent text (move right)">
+<!ENTITY AlignPopupButton.tooltip "Choose text alignment">
+<!ENTITY InsertPopupButton.tooltip "Insert a Link, Anchor, Image, Horizontal Line, or Table">
+<!ENTITY alignLeftButton.tooltip "Align text along left margin">
+<!ENTITY alignCenterButton.tooltip "Align text centered">
+<!ENTITY alignRightButton.tooltip "Align text along right margin">
+<!ENTITY alignjustifyButton.tooltip "Align text along left and right margins">
+
+<!-- Formatting toolbar not used, but may be in future -->
+<!ENTITY formatToolbar.boldChar "B">
+<!ENTITY formatToolbar.italicChar "I">
+<!ENTITY formatToolbar.underlineChar "U">
+
+<!-- Used with color pickers in Format toolbar and Format Menu -->
+<!ENTITY colorPicker.default.label "Reader's default color">
+<!ENTITY colorPicker.default.accesskey "r">
+<!ENTITY colorLabel.label "Color:">
+<!ENTITY ok.label "OK">
+
+<!-- Display Mode toolbar and View menu items -->
+<!ENTITY NormalModeTab.label "Normal">
+<!ENTITY NormalMode.label "Normal Edit Mode">
+<!ENTITY NormalMode.accesskey "n">
+<!ENTITY NormalMode.tooltip "Show table borders and named anchors">
+<!ENTITY AllTagsMode.label "HTML Tags">
+<!ENTITY AllTagsMode.accesskey "A">
+<!ENTITY AllTagsMode.tooltip "Display icons for all HTML tags">
+
+<!ENTITY HTMLSourceMode.label "HTML Source">
+<!-- Toolbar has an image with "HTML" text, so don't include it in the string -->
+<!ENTITY SourceMode.label "Source">
+<!ENTITY HTMLSourceMode.accesskey "h">
+<!ENTITY HTMLSourceMode.tooltip "Edit HTML source">
+<!ENTITY PreviewMode.label "Preview">
+<!ENTITY PreviewMode.accesskey "p">
+<!ENTITY PreviewMode.tooltip "Display as WYSIWYG (as in the browser)">
+
+<!-- LOCALIZATION NOTE: Do NOT translate text for 'SourceTabDirection'
+ Use latin "ltr" if you want the <html> image to left of the
+ 'SourceMode.label' text defined above,
+ or use latin "rtl" if you want this image to the right of text
+ This is the value of the HTML 'dir' attribute
+-->
+<!ENTITY SourceTabDirection "ltr">
+
+<!-- Structure Toolbar Context Menu items -->
+<!ENTITY structSelect.label "Select">
+<!ENTITY structSelect.accesskey "s">
+<!ENTITY structRemoveTag.label "Remove tag">
+<!ENTITY structRemoveTag.accesskey "r">
+<!ENTITY structChangeTag.label "Change tag">
+<!ENTITY structChangeTag.accesskey "c">
+
+<!-- TOC manipulation -->
+<!ENTITY insertTOC.label "Insert">
+<!ENTITY insertTOC.accesskey "i">
+<!ENTITY updateTOC.label "Update">
+<!ENTITY updateTOC.accesskey "u">
+<!ENTITY removeTOC.label "Remove">
+<!ENTITY removeTOC.accesskey "r">
+<!ENTITY tocMenu.label "Table of Contents…">
+<!ENTITY tocMenu.accesskey "b">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editorPrefsOverlay.dtd
@@ -0,0 +1,9 @@
+
+<!--LOCALIZATION NOTE (editorCheck.label): DONT_TRANSLATE -->
+<!ENTITY editorCheck.label "Composer">
+<!ENTITY editorCheck.accesskey "c">
+
+<!ENTITY compose.label "Composer">
+<!ENTITY editing.label "New Page Settings">
+<!ENTITY toolbars.label "Toolbars">
+<!ENTITY publish.label "Publishing">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/editorSmileyOverlay.dtd
@@ -0,0 +1,91 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Smiley Overlay.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Smiley Menu items -->
+<!ENTITY insertSmiley.label "Smiley">
+<!ENTITY insertSmiley.accesskey "S">
+
+<!ENTITY smiley1Cmd.label "Smile">
+<!ENTITY smiley1Cmd.accesskey "S">
+<!ENTITY smiley1Cmd.tooltip "Insert a smiley face">
+<!ENTITY smiley2Cmd.label "Frown">
+<!ENTITY smiley2Cmd.accesskey "F">
+<!ENTITY smiley2Cmd.tooltip "Insert a frown face">
+<!ENTITY smiley3Cmd.label "Wink">
+<!ENTITY smiley3Cmd.accesskey "W">
+<!ENTITY smiley3Cmd.tooltip "Insert a wink face">
+<!ENTITY smiley4Cmd.label "Tongue-out">
+<!ENTITY smiley4Cmd.accesskey "T">
+<!ENTITY smiley4Cmd.tooltip "Insert a tongue-out face">
+<!ENTITY smiley5Cmd.label "Laughing">
+<!ENTITY smiley5Cmd.accesskey "L">
+<!ENTITY smiley5Cmd.tooltip "Insert a laughing face">
+<!ENTITY smiley6Cmd.label "Embarrassed">
+<!ENTITY smiley6Cmd.accesskey "E">
+<!ENTITY smiley6Cmd.tooltip "Insert an embarrassed face">
+<!ENTITY smiley7Cmd.label "Undecided">
+<!ENTITY smiley7Cmd.accesskey "U">
+<!ENTITY smiley7Cmd.tooltip "Insert an undecided face">
+<!ENTITY smiley8Cmd.label "Surprise">
+<!ENTITY smiley8Cmd.accesskey "p">
+<!ENTITY smiley8Cmd.tooltip "Insert a surprised face">
+<!ENTITY smiley9Cmd.label "Kiss">
+<!ENTITY smiley9Cmd.accesskey "K">
+<!ENTITY smiley9Cmd.tooltip "Insert a kiss face">
+<!ENTITY smiley10Cmd.label "Yell">
+<!ENTITY smiley10Cmd.accesskey "Y">
+<!ENTITY smiley10Cmd.tooltip "Insert a yelling face">
+<!ENTITY smiley11Cmd.label "Cool">
+<!ENTITY smiley11Cmd.accesskey "C">
+<!ENTITY smiley11Cmd.tooltip "Insert a cool face">
+<!ENTITY smiley12Cmd.label "Money-Mouth">
+<!ENTITY smiley12Cmd.accesskey "M">
+<!ENTITY smiley12Cmd.tooltip "Insert a money-mouth face">
+<!ENTITY smiley13Cmd.label "Foot-in-Mouth">
+<!ENTITY smiley13Cmd.accesskey "o">
+<!ENTITY smiley13Cmd.tooltip "Insert a foot-in-mouth face">
+<!ENTITY smiley14Cmd.label "Innocent">
+<!ENTITY smiley14Cmd.accesskey "I">
+<!ENTITY smiley14Cmd.tooltip "Insert an innocent face">
+<!ENTITY smiley15Cmd.label "Cry">
+<!ENTITY smiley15Cmd.accesskey "r">
+<!ENTITY smiley15Cmd.tooltip "Insert a crying face">
+<!ENTITY smiley16Cmd.label "Lips-are-Sealed">
+<!ENTITY smiley16Cmd.accesskey "a">
+<!ENTITY smiley16Cmd.tooltip "Insert a lips-are-sealed face">
+<!ENTITY SmileButton.tooltip "Insert a smiley face">
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/pref-composer.dtd
@@ -0,0 +1,39 @@
+<!-- extracted from content/pref-composer.xul -->
+
+<!--LOCALIZATION NOTE : FILE 'Composer' prefs dialog. Similar to Communcator 4.x Document Properties/Colors and Background -->
+
+<!--LOCALIZATION NOTE (pref.composer.title): DONT_TRANSLATE -->
+<!ENTITY pref.composer.title "Composer">
+
+<!ENTITY saving "Saving">
+<!ENTITY AutoSaveCheck "Automatically save every">
+<!ENTITY minText "minutes">
+
+<!ENTITY exterLegend.label "External Editors">
+<!ENTITY htmlSource "HTML Source:">
+<!ENTITY imageeditor "Images:">
+<!ENTITY chooseButton.label "Choose">
+
+<!ENTITY recentFiles.title "Recent Pages Menu">
+<!ENTITY documentsInMenu.label "Maximum number of pages listed:">
+<!ENTITY documentsInMenu.accesskey "n">
+
+<!ENTITY savingFiles.title "When Saving or Publishing Pages">
+<!ENTITY preserveExisting.label "Preserve original source formatting">
+<!ENTITY preserveExisting.accesskey "P">
+<!ENTITY preserveExisting.tooltip "Preserves line breaks and page's original formatting">
+<!ENTITY saveAssociatedFiles.label "Save images and other associated files when saving pages">
+<!ENTITY saveAssociatedFiles.accesskey "S">
+<!ENTITY showPublishDialog.label "Always show Publish dialog when publishing pages">
+<!ENTITY showPublishDialog.accesskey "A">
+
+<!ENTITY composerEditing.label "Editing">
+<!ENTITY spellCheckInline.label "Check spelling as you type">
+<!ENTITY spellCheckInline.accesskey "C">
+<!ENTITY maintainStructure.label "Maintain table layout when inserting or deleting cells">
+<!ENTITY maintainStructure.tooltip "Preserves table's rectangular shape by automatically adding cells after inserting or deleting cells">
+<!ENTITY maintainStructure.accesskey "M">
+<!ENTITY useCSS.label "Use CSS styles instead of HTML elements and attributes">
+<!ENTITY useCSS.accesskey "U">
+<!ENTITY crInPCreatesNewP.label "Return in a paragraph always creates a new paragraph">
+<!ENTITY crInPCreatesNewP.accesskey "R">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/pref-editing.dtd
@@ -0,0 +1,28 @@
+<!ENTITY pref.editing.title "New Page Settings">
+
+<!ENTITY authorName.label "Author:">
+<!ENTITY authorName.accesskey "u">
+<!ENTITY pageColorHeader "Default Page Appearance">
+
+<!ENTITY defaultColorsRadio.label "Reader's default colors (Don't set colors in page)">
+<!ENTITY defaultColors.accesskey "d">
+<!ENTITY customColorsRadio.label "Use custom colors:">
+<!ENTITY customColors.accesskey "c">
+
+<!ENTITY normalText.label "Normal text">
+<!ENTITY normalText.accesskey "N">
+<!ENTITY linkText.label "Link text">
+<!ENTITY linkText.accesskey "L">
+<!ENTITY activeLinkText.label "Active link text">
+<!ENTITY activeLinkText.accesskey "A">
+<!ENTITY visitedLinkText.label "Visited link text">
+<!ENTITY visitedLinkText.accesskey "V">
+<!ENTITY background.label "Background:">
+<!ENTITY background.accesskey "B">
+<!ENTITY colon.character ":">
+
+<!ENTITY backgroundImage.label "Background image:">
+<!ENTITY backgroundImage.accesskey "m">
+<!ENTITY chooseFile.label "Choose File…">
+<!ENTITY chooseFile.accesskey "o">
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/composer/pref-toolbars.dtd
@@ -0,0 +1,71 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Editor Toolbar Preferences.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY pref.toolbars.title "Toolbars">
+
+<!ENTITY composition.caption "Show these buttons in the Composition Toolbar:">
+
+<!ENTITY new.label "New">
+<!ENTITY open.label "Open">
+<!ENTITY save.label "Save">
+<!ENTITY publish.label "Publish">
+<!ENTITY preview.label "Browse">
+<!ENTITY cut.label "Cut">
+<!ENTITY copy.label "Copy">
+<!ENTITY paste.label "Paste">
+<!ENTITY print.label "Print">
+<!ENTITY find.label "Find">
+<!ENTITY image.label "Image">
+<!ENTITY hline.label "H. Line">
+<!ENTITY table.label "Table">
+<!ENTITY link.label "Link">
+<!ENTITY anchor.label "Anchor">
+
+<!ENTITY formatting.caption "Show these buttons in the Formatting Toolbar:">
+
+<!ENTITY smaller.label "Smaller">
+<!ENTITY larger.label "Larger">
+<!ENTITY bold.label "Bold">
+<!ENTITY bullets.label "Bullets">
+<!ENTITY numbers.label "Numbers">
+<!ENTITY italic.label "Italic">
+<!ENTITY outdent.label "Outdent">
+<!ENTITY indent.label "Indent">
+<!ENTITY underline.label "Underline">
+
+<!ENTITY absolutePosition.label "Absolute positioning">
+<!ENTITY decreaseZIndex.label "Send to back">
+<!ENTITY increaseZIndex.label "Bring to front">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdAdvancedEdit.dtd
@@ -0,0 +1,52 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Ben Goodger
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY WindowTitle.label "Advanced Property Editor">
+<!ENTITY AttName.label "Attribute: ">
+<!ENTITY AttValue.label "Value: ">
+<!ENTITY PropertyName.label "Property: ">
+<!ENTITY currentattributesfor.label "Current attributes for: ">
+<!ENTITY tree.attributeHeader.label "Attribute">
+<!ENTITY tree.propertyHeader.label "Property">
+<!ENTITY tree.valueHeader.label "Value">
+<!ENTITY tabHTML.label "HTML Attributes">
+<!ENTITY tabCSS.label "Inline Style">
+<!ENTITY tabJSE.label "JavaScript Events">
+
+<!ENTITY editAttribute.label "Click on an item above to edit its value">
+<!ENTITY removeAttribute.label "Remove">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdColorPicker.dtd
@@ -0,0 +1,55 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Color">
+<!ENTITY lastPickedColor.label "Last-picked color">
+<!ENTITY lastPickedColor.accessKey "L">
+<!ENTITY setColor1.label "Click on a color or">
+<!ENTITY setColor2.label "enter an HTML color string">
+<!ENTITY setColor2.accessKey "H">
+<!ENTITY setColorExample.label "(e.g.: "#0000ff" or "blue"):">
+<!ENTITY default.label "Default">
+<!ENTITY default.accessKey "D">
+<!ENTITY palette.label "Palette:">
+<!ENTITY standardPalette.label "Standard">
+<!ENTITY webPalette.label "All web colors">
+<!ENTITY background.label "Background for:">
+<!ENTITY background.accessKey "B">
+<!ENTITY table.label "Table">
+<!ENTITY table.accessKey "T">
+<!ENTITY cell.label "Cell(s)">
+<!ENTITY cell.accessKey "C">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdConvertToTable.dtd
@@ -0,0 +1,48 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Convert To Table">
+<!ENTITY instructions1.label "Composer creates a new table row for each paragraph in the selection.">
+<!ENTITY instructions2.label "Choose the character used to separate the selection into columns:">
+<!ENTITY commaRadio.label "Comma">
+<!ENTITY spaceRadio.label "Space">
+<!ENTITY otherRadio.label "Other Character:">
+<!ENTITY deleteCharCheck.label "Delete separator character">
+<!ENTITY collapseSpaces.label "Ignore extra spaces">
+<!ENTITY collapseSpaces.tooltip "Convert adjacent spaces to one separator">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdDialogOverlay.dtd
@@ -0,0 +1,51 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY AdvancedEditButton.label "Advanced Edit…">
+<!ENTITY AdvancedEditButton.accessKey "E">
+<!ENTITY AdvancedEditButton.tooltip "Add or modify HTML attributes, style attributes, and JavaScript">
+<!ENTITY chooseFileButton.label "Choose File...">
+<!ENTITY chooseFileButton.accessKey "F">
+<!ENTITY chooseFileLinkButton.label "Choose File...">
+<!ENTITY chooseFileLinkButton.accessKey "o">
+<!ENTITY makeUrlRelative.label "URL is relative to page location">
+<!ENTITY makeUrlRelative.accessKey "r">
+<!ENTITY makeUrlRelative.tooltip "Change between relative and absolute URL. You must first save the page to change this.">
+
+<!-- Shared by Link and Image dialogs -->
+<!ENTITY LinkURLEditField.label "Enter a web page location, a local file, or select a Named Anchor or Heading from the popup list:">
+<!ENTITY LinkURLEditField.accessKey "L">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdLinkChecker.dtd
@@ -0,0 +1,46 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manxke (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Check Image and Link Locations">
+<!ENTITY urlsNotFound.label "The following image or link locations were not found:">
+<!ENTITY notFoundKey.label "("X" = file not found, "?" = timed-out attempting to connect.)">
+<!ENTITY changeUrlButton.label "Change Location of Selected Item">
+<!ENTITY succeeded.label "Succeeded">
+<!ENTITY failed.label "Failed">
+<!ENTITY closeButton.label "Close">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EdNamedAnchorProperties.dtd
@@ -0,0 +1,43 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Named Anchor Properties">
+<!ENTITY anchorNameEditField.label "Anchor Name:">
+<!ENTITY anchorNameEditField.accessKey "N">
+<!ENTITY nameInput.tooltip "Enter a unique name for this named anchor (target)">
+
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditConflict.dtd
@@ -0,0 +1,43 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Select Edit Changes">
+<!ENTITY conflictWarning.label "This page has been modified by another program, but you also have unsaved changes in Composer.">
+<!ENTITY conflictResolve.label "Select which version to keep:">
+<!ENTITY keepCurrentPageButton.label "Keep current page changes">
+<!ENTITY useOtherPageButton.label "Replace current page with other changes">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorButtonProperties.dtd
@@ -0,0 +1,59 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Button Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Button Properties">
+
+<!ENTITY Settings.label "Settings">
+
+<!ENTITY ButtonType.label "Type">
+<!ENTITY ButtonType.accesskey "T">
+<!ENTITY submit.value "Submit">
+<!ENTITY reset.value "Reset">
+<!ENTITY button.value "Button">
+
+<!ENTITY ButtonName.label "Name:">
+<!ENTITY ButtonName.accesskey "N">
+<!ENTITY ButtonValue.label "Value:">
+<!ENTITY ButtonValue.accesskey "V">
+<!ENTITY tabIndex.label "Tab Index:">
+<!ENTITY tabIndex.accesskey "I">
+<!ENTITY ButtonDisabled.label "Disabled">
+<!ENTITY ButtonDisabled.accesskey "D">
+<!ENTITY AccessKey.label "Access Key:">
+<!ENTITY AccessKey.accesskey "K">
+
+<!ENTITY RemoveButton.label "Remove Button">
+<!ENTITY RemoveButton.accesskey "R">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorColorProperties.dtd
@@ -0,0 +1,61 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Page Colors and Background">
+<!ENTITY pageColors.label "Page Colors">
+<!ENTITY defaultColorsRadio.label "Reader's default colors (Don't set colors in page)">
+<!ENTITY defaultColorsRadio.accessKey "D">
+<!ENTITY defaultColorsRadio.tooltip "Use the color settings from the viewer (reader's) browser only">
+<!ENTITY customColorsRadio.label "Use custom colors:">
+<!ENTITY customColorsRadio.accessKey "C">
+<!ENTITY customColorsRadio.tooltip "These color settings override the viewer's browser settings">
+
+<!ENTITY normalText.label "Normal text">
+<!ENTITY normalText.accessKey "N">
+<!ENTITY linkText.label "Link text">
+<!ENTITY linkText.accessKey "L">
+<!ENTITY activeLinkText.label "Active link text">
+<!ENTITY activeLinkText.accessKey "A">
+<!ENTITY visitedLinkText.label "Visited link text">
+<!ENTITY visitedLinkText.accessKey "V">
+<!ENTITY background.label "Background:">
+<!ENTITY background.accessKey "B">
+<!ENTITY colon.character ":">
+<!ENTITY backgroundImage.label "Background Image:">
+<!ENTITY backgroundImage.accessKey "m">
+<!ENTITY backgroundImage.tooltip "Use an image file as the background for your page">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorFieldSetProperties.dtd
@@ -0,0 +1,52 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Button Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Field Set Properties">
+
+<!ENTITY Legend.label "Legend">
+<!ENTITY Legend.accesskey "L">
+
+<!ENTITY EditLegendText.label "Edit Legend:">
+<!ENTITY EditLegendText.accesskey "T">
+<!ENTITY LegendAlign.label "Align Legend:">
+<!ENTITY LegendAlign.accesskey "A">
+<!ENTITY AlignDefault.label "Default">
+<!ENTITY AlignLeft.label "Left">
+<!ENTITY AlignCenter.label "Center">
+<!ENTITY AlignRight.label "Right">
+
+<!ENTITY RemoveFieldSet.label "Remove Field Set">
+<!ENTITY RemoveFieldSet.accesskey "R">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorFormProperties.dtd
@@ -0,0 +1,53 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Form Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Form Properties">
+
+<!ENTITY Settings.label "Settings">
+
+<!ENTITY FormName.label "Form Name:">
+<!ENTITY FormName.accesskey "N">
+<!ENTITY FormAction.label "Action URL:">
+<!ENTITY FormAction.accesskey "A">
+<!ENTITY FormMethod.label "Method:">
+<!ENTITY FormMethod.accesskey "M">
+<!ENTITY FormEncType.label "Encoding:">
+<!ENTITY FormEncType.accesskey "c">
+<!ENTITY FormTarget.label "Target Frame:">
+<!ENTITY FormTarget.accesskey "T">
+
+<!ENTITY RemoveForm.label "Remove Form">
+<!ENTITY RemoveForm.accesskey "R">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorHLineProperties.dtd
@@ -0,0 +1,60 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Horizontal Line Properties">
+
+<!ENTITY dimensionsBox.label "Dimensions">
+<!ENTITY heightEditField.label "Height:">
+<!ENTITY heightEditField.accessKey "G">
+<!ENTITY widthEditField.label "Width:">
+<!ENTITY widthEditField.accessKey "W">
+<!ENTITY pixelsPopup.value "pixels">
+<!ENTITY alignmentBox.label "Alignment">
+<!ENTITY leftRadio.label "Left">
+<!ENTITY leftRadio.accessKey "L">
+<!ENTITY centerRadio.label "Center">
+<!ENTITY centerRadio.accessKey "C">
+<!ENTITY rightRadio.label "Right">
+<!ENTITY rightRadio.accessKey "R">
+
+<!ENTITY threeDShading.label "3-D Shading">
+<!ENTITY threeDShading.accessKey "S">
+<!ENTITY saveSettings.label "Use as Default">
+<!ENTITY saveSettings.accessKey "D">
+<!ENTITY saveSettings.tooltip "Save these settings to use when inserting new horizontal lines">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorImageMap.dtd
@@ -0,0 +1,104 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Dan Haddix (dan6992@hotmail.com)
+ - Brian King (briano9@yahoo.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- These strings are for use specifically in the editor's image map dialog. -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Image Map Editor">
+
+<!-- Menu Items -->
+<!-- File menu -->
+<!ENTITY mapfileMenu.label "File">
+<!ENTITY mapfilemenu.accesskey "f">
+<!ENTITY clearCmd.label "Clear">
+<!ENTITY mapfileclear.accesskey "a">
+<!ENTITY closeCmd.label "Close">
+<!ENTITY mapfileclose.accesskey "c">
+
+<!-- Edit menu -->
+<!ENTITY mapeditMenu.label "Edit">
+<!ENTITY mapeditmenu.accesskey "e">
+<!ENTITY cutCmd.label "Cut">
+<!ENTITY mapeditcut.accesskey "t">
+<!ENTITY copyCmd.label "Copy">
+<!ENTITY mapeditcopy.accesskey "c">
+<!ENTITY pasteCmd.label "Paste">
+<!ENTITY mapeditpaste.accesskey "p">
+<!ENTITY selectallCmd.label "Select All">
+<!ENTITY mapselectall.accesskey "s">
+<!ENTITY propsCmd.label "Hotspot Properties">
+<!ENTITY mapeditprops.accesskey "h">
+
+<!-- View menu -->
+<!ENTITY mapviewMenu.label "View">
+<!ENTITY mapviewmenu.accesskey "v">
+<!ENTITY showhideTbarCmd.label "Hide Toolbar">
+<!ENTITY mapviewtbar.accesskey "t">
+<!-- Scaling -->
+<!ENTITY mapviewScale.label "Scale">
+<!ENTITY mapviewscale.accesskey "S">
+<!ENTITY apercentCmd.label "100">
+<!ENTITY zoomone.accesskey "1">
+<!ENTITY bpercentCmd.label "200">
+<!ENTITY zoomtwo.accesskey "2">
+<!ENTITY cpercentCmd.label "400">
+<!ENTITY zoomthree.accesskey "4">
+<!-- end scaling-->
+<!ENTITY contrastCmd.label "Contrast">
+<!ENTITY contrast.accesskey "n">
+
+<!-- Help menu -->
+<!ENTITY maphelpMenu.label "Help">
+<!ENTITY maphelpmenu.accesskey "h">
+<!ENTITY aboutCmd.label "About">
+<!ENTITY about.accesskey "b">
+
+<!ENTITY zoominCmd.label "Zoom In">
+<!ENTITY zoomoutCmd.label "Zoom Out">
+<!ENTITY delSpotCmd.label "Delete Spot">
+
+<!-- Keys -->
+<!ENTITY clear.accesskey "d">
+<!ENTITY selectall.accesskey "a">
+<!ENTITY close.accesskey "l">
+<!ENTITY cut.accesskey "x">
+<!ENTITY copy.accesskey "c">
+<!ENTITY paste.accesskey "v">
+<!ENTITY props.accesskey "p">
+<!ENTITY tbar.accesskey "t">
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorImageMapHotSpot.dtd
@@ -0,0 +1,58 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Dan Haddix (dan6992@hotmail.com)
+ - Brian King (briano9@yahoo.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+
+<!ENTITY windowTitle.label "Hotspot Properties">
+
+<!ENTITY link.label "Hotspot Link">
+<!ENTITY urlFieldset.label "Hotspot URL:">
+<!ENTITY altFieldset.label "Hotspot Alt Text:">
+<!ENTITY browseButton.label "Browse…">
+<!ENTITY targetFieldset.label "Target Setting">
+<!ENTITY target.label "Hotspot Target">
+
+<!-- Targets -->
+<!ENTITY commonFieldset.label "Common Targets:">
+<!ENTITY none.value "(none)">
+<!ENTITY same.value "Same Frame">
+<!ENTITY whole.value "Whole Page">
+<!ENTITY new.value "New Window">
+<!ENTITY parent.value "Parent Frame">
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorImageProperties.dtd
@@ -0,0 +1,119 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- These strings are for use specifically in the editor's image and form image dialogs. -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Image Properties">
+
+<!ENTITY pixelsPopup.value "pixels">
+<!ENTITY percentPopup.value "percent">
+
+<!-- These are in the Location tab panel -->
+<!ENTITY locationEditField.label "Image Location:">
+<!ENTITY locationEditField.accessKey "L">
+<!ENTITY locationEditField.tooltip "Type the image's filename or location">
+<!ENTITY title.label "Tooltip:">
+<!ENTITY title.accessKey "T">
+<!ENTITY title.tooltip "The html 'title' attribute that displays as a tooltip">
+<!ENTITY altText.label "Alternate text:">
+<!ENTITY altText.accessKey "A">
+<!ENTITY altTextEditField.tooltip "Type text to display in place of the image">
+<!ENTITY noAltText.label "Don't use alternate text">
+<!ENTITY noAltText.accessKey "D">
+
+<!ENTITY previewBox.label "Image Preview">
+<!ENTITY MoreFewerButton.tooltip "Display more or fewer properties to edit">
+
+<!-- These controls are in the Dimensions tab panel -->
+<!-- actualSize.label should be same as actualSizeRadio.label + ":" -->
+<!ENTITY actualSize.label "Actual Size:">
+<!ENTITY actualSizeRadio.label "Actual Size">
+<!ENTITY actualSizeRadio.accessKey "A">
+<!ENTITY actualSizeRadio.tooltip "Revert to the image's actual size">
+<!ENTITY customSizeRadio.label "Custom Size">
+<!ENTITY customSizeRadio.accessKey "S">
+<!ENTITY customSizeRadio.tooltip "Change the image's size as displayed in the page">
+<!ENTITY heightEditField.label "Height:">
+<!ENTITY heightEditField.accessKey "G">
+<!ENTITY widthEditField.label "Width:">
+<!ENTITY widthEditField.accessKey "W">
+<!ENTITY constrainCheckbox.label "Constrain">
+<!ENTITY constrainCheckbox.accessKey "C">
+<!ENTITY constrainCheckbox.tooltip "Maintain the image's aspect ratio">
+
+<!-- These controls are in the Image Map box of the expanded area -->
+<!ENTITY imagemapBox.label "Image Map">
+<!ENTITY removeImageMapButton.label "Remove">
+<!ENTITY removeImageMapButton.accessKey "R">
+<!ENTITY editImageMapButton.label "Edit…">
+<!ENTITY editImageMapButton.tooltip "Create clickable hotspots for this image">
+
+<!-- These are the options for image alignment -->
+<!ENTITY alignment.label "Align Text to Image">
+<!ENTITY bottomPopup.value "At the bottom">
+<!ENTITY topPopup.value "At the top">
+<!ENTITY centerPopup.value "In the center">
+<!ENTITY wrapRightPopup.value "Wrap to the right">
+<!ENTITY wrapLeftPopup.value "Wrap to the left">
+
+<!-- These controls are in the Spacing Box -->
+<!ENTITY spacingBox.label "Spacing">
+<!ENTITY spacingBox.tooltip "Type a number for the amount of space around image">
+<!ENTITY leftRightEditField.label "Left and Right:">
+<!ENTITY leftRightEditField.accessKey "L">
+<!ENTITY topBottomEditField.label "Top and Bottom:">
+<!ENTITY topBottomEditField.accessKey "T">
+<!ENTITY borderEditField.label "Solid Border:">
+<!ENTITY borderEditField.accessKey "B">
+
+<!-- These controls are in the Link Box -->
+<!ENTITY showImageLinkBorder.label "Show border around linked image">
+<!ENTITY showImageLinkBorder.accessKey "B">
+
+<!-- These controls may be added some day; currently not used -->
+<!ENTITY makePageBackgroundCheckbox.label "Make Page Background">
+<!ENTITY makePageBackgroundCheckbox.tooltip "Use image as background for your page">
+<!ENTITY editImageButton.label "Edit Image">
+<!ENTITY editImageButton.tooltip "Edit image file in another program">
+
+<!-- These tabs are currently used in the image input dialog -->
+<!ENTITY imageInputTab.label "Form">
+<!ENTITY imageLocationTab.label "Location">
+<!ENTITY imageDimensionsTab.label "Dimensions">
+<!ENTITY imageAppearanceTab.label "Appearance">
+<!ENTITY imageLinkTab.label "Link">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorInputProperties.dtd
@@ -0,0 +1,80 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Input Tag Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Form Field Properties">
+<!ENTITY windowTitleImage.label "Form Image Properties">
+
+<!ENTITY InputType.label "Field Type">
+<!ENTITY InputType.accesskey "T">
+<!ENTITY text.value "Text">
+<!ENTITY password.value "Password">
+<!ENTITY checkbox.value "Check Box">
+<!ENTITY radio.value "Radio Button">
+<!ENTITY submit.value "Submit Button">
+<!ENTITY reset.value "Reset Button">
+<!ENTITY file.value "File">
+<!ENTITY hidden.value "Hidden">
+<!ENTITY image.value "Image">
+<!ENTITY button.value "Button">
+
+<!ENTITY InputSettings.label "Field Settings">
+<!ENTITY InputName.label "Field Name:">
+<!ENTITY GroupName.label "Group Name:">
+<!ENTITY Name.accesskey "N">
+<!ENTITY InputValue.label "Field Value:">
+<!ENTITY InitialValue.label "Initial Value:">
+<!ENTITY Value.accesskey "V">
+<!ENTITY InputChecked.label "Initially Checked">
+<!ENTITY InputChecked.accesskey "C">
+<!ENTITY InputSelected.label "Initially Selected">
+<!ENTITY InputSelected.accesskey "S">
+<!ENTITY InputReadOnly.label "Read Only">
+<!ENTITY InputReadOnly.accesskey "R">
+<!ENTITY InputDisabled.label "Disabled">
+<!ENTITY InputDisabled.accesskey "D">
+<!ENTITY tabIndex.label "Tab Index:">
+<!ENTITY tabIndex.accesskey "I">
+<!ENTITY TextSize.label "Field Size:">
+<!ENTITY TextSize.accesskey "F">
+<!ENTITY TextLength.label "Maximum Length:">
+<!ENTITY TextLength.accesskey "L">
+<!ENTITY AccessKey.label "Access Key:">
+<!ENTITY AccessKey.accesskey "K">
+<!ENTITY Accept.label "Accept Types:">
+<!ENTITY Accept.accesskey "A">
+
+<!ENTITY ImageProperties.label "Image Properties…">
+<!ENTITY ImageProperties.accesskey "E">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertChars.dtd
@@ -0,0 +1,52 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Insert Character">
+<!ENTITY category.label "Category">
+<!ENTITY letter.label "Letter:">
+<!ENTITY letter.accessKey "L">
+<!ENTITY character.label "Character:">
+<!ENTITY character.accessKey "C">
+<!ENTITY accentUpper.label "Accent Uppercase">
+<!ENTITY accentLower.label "Accent Lowercase">
+<!ENTITY otherUpper.label "Other Uppercase">
+<!ENTITY otherLower.label "Other Lowercase">
+<!ENTITY commonSymbols.label "Common Symbols">
+<!ENTITY insertButton.label "Insert">
+<!ENTITY closeButton.label "Close">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertSource.dtd
@@ -0,0 +1,48 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Insert HTML">
+<!ENTITY sourceEditField.label "Enter HTML tags and text:">
+<!ENTITY example.label "Example: ">
+<!-- LOCALIZATION NOTE (exampleOpenTag.label): DONT_TRANSLATE: they are text for HTML tagnames: "<i>" and "</i>" -->
+<!ENTITY exampleOpenTag.label "<i>">
+<!-- LOCALIZATION NOTE (exampleCloseTag.label): DONT_TRANSLATE: they are text for HTML tagnames: "<i>" and "</i>" -->
+<!ENTITY exampleCloseTag.label "</i>">
+<!ENTITY exampleText.label "Hello World!">
+<!ENTITY insertButton.label "Insert">
+<!ENTITY insertButton.accesskey "I">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTOC.dtd
@@ -0,0 +1,50 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is TOCMaker.
+ -
+ - The Initial Developer of the Original Code is
+ - Daniel Glazman.
+ - Portions created by the Initial Developer are Copyright (C) 2002
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Original author: Daniel Glazman (daniel@glazman.org)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY Window.title "Table of Contents">
+<!ENTITY buildToc.label "Build table of contents from:">
+<!ENTITY style.label "Style:">
+<!ENTITY tag.label "Tag:">
+<!ENTITY class.label "Class:">
+<!ENTITY header1.label "Level 1">
+<!ENTITY header2.label "Level 2">
+<!ENTITY header3.label "Level 3">
+<!ENTITY header4.label "Level 4">
+<!ENTITY header5.label "Level 5">
+<!ENTITY header6.label "Level 6">
+<!ENTITY makeReadOnly.label "Make the table of contents read-only">
+<!ENTITY orderedList.label "Number all entries in the table of contents">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTable.dtd
@@ -0,0 +1,51 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-2000
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Insert Table">
+
+<!ENTITY size.label "Size">
+<!ENTITY numRowsEditField.label "Rows:">
+<!ENTITY numRowsEditField.accessKey "R">
+<!ENTITY numColumnsEditField.label "Columns:">
+<!ENTITY numColumnsEditField.accessKey "C">
+<!ENTITY widthEditField.label "Width:">
+<!ENTITY widthEditField.accessKey "W">
+<!ENTITY borderEditField.label "Border:">
+<!ENTITY borderEditField.accessKey "B">
+<!ENTITY borderEditField.tooltip "Type a number for the table's border, or type zero (0) for no border">
+<!ENTITY pixels.label "pixels">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorLabelProperties.dtd
@@ -0,0 +1,50 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Button Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Label Properties">
+
+<!ENTITY Settings.label "Settings">
+<!ENTITY Settings.accesskey "S">
+
+<!ENTITY EditLabelText.label "Edit Text:">
+<!ENTITY EditLabelText.accesskey "T">
+<!ENTITY LabelFor.label "For Control:">
+<!ENTITY LabelFor.accesskey "F">
+<!ENTITY AccessKey.label "Access Key:">
+<!ENTITY AccessKey.accesskey "K">
+
+<!ENTITY RemoveLabel.label "Remove Label">
+<!ENTITY RemoveLabel.accesskey "R">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorLinkProperties.dtd
@@ -0,0 +1,39 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Link Properties">
+<!ENTITY LinkURLBox.label "Link Location">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorListProperties.dtd
@@ -0,0 +1,54 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "List Properties">
+
+<!ENTITY ListType.label "List Type">
+<!ENTITY bulletStyle.label "Bullet Style:">
+<!ENTITY startingNumber.label "Start at:">
+<!ENTITY startingNumber.accessKey "S">
+<!ENTITY none.value "None">
+<!ENTITY bulletList.value "Bullet (Unnumbered) List">
+<!ENTITY numberList.value "Numbered List">
+<!ENTITY definitionList.value "Definition List">
+<!ENTITY changeListMsg.label "When changing list type:">
+<!ENTITY changeEntireListRadio.label "Change entire list">
+<!ENTITY changeEntireListRadio.accessKey "C">
+<!ENTITY changeSelectedRadio.label "Change just selected items">
+<!ENTITY changeSelectedRadio.accessKey "I">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorPageProperties.dtd
@@ -0,0 +1,50 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Page Properties">
+<!ENTITY location.label "Location:">
+<!ENTITY lastModified.label "Last Modified:">
+<!ENTITY titleInput.label "Title:">
+<!ENTITY titleInput.accessKey "T">
+<!ENTITY authorInput.label "Author:">
+<!ENTITY authorInput.accessKey "A">
+<!ENTITY descriptionInput.label "Description:">
+<!ENTITY descriptionInput.accessKey "D">
+<!ENTITY locationNewPage.label "[New page, not saved yet]">
+<!ENTITY EditHEADSource1.label "Advanced users:">
+<!ENTITY EditHEADSource2.label "To edit other contents of the <head> region, use "HTML Source" in the View Menu or Edit Mode Toolbar.">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorPersonalDictionary.dtd
@@ -0,0 +1,53 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Personal Dictionary">
+
+<!ENTITY wordEditField.label "New word:">
+<!ENTITY wordEditField.accessKey "N">
+<!ENTITY AddButton.label "Add">
+<!ENTITY AddButton.accessKey "A">
+<!ENTITY DictionaryList.label "Words in dictionary:">
+<!ENTITY DictionaryList.accessKey "W">
+<!ENTITY ReplaceButton.label "Replace">
+<!ENTITY ReplaceButton.accessKey "R">
+<!ENTITY RemoveButton.label "Remove">
+<!ENTITY RemoveButton.accessKey "e">
+
+<!ENTITY CloseButton.label "Close">
+<!ENTITY CloseButton.accessKey "C">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorPublish.dtd
@@ -0,0 +1,103 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Publish Page">
+<!ENTITY windowTitleSettings.label "Publish Settings">
+
+<!ENTITY publishTab.label "Publish">
+<!ENTITY settingsTab.label "Settings">
+
+<!ENTITY publishButton.label "Publish">
+
+<!-- Publish Tab Panel -->
+<!ENTITY siteList.label "Site Name:">
+<!ENTITY siteList.accesskey "e">
+<!ENTITY siteList.tooltip "Choose the site that you want to publish to">
+<!ENTITY newSiteButton.label "New Site">
+<!ENTITY newSiteButton.accesskey "N">
+<!ENTITY docDirList.label "Site subdirectory for this page:">
+<!ENTITY docDirList.accesskey "S">
+<!ENTITY docDirList.tooltip "Choose or enter the name of the remote subdirectory for this page">
+<!ENTITY publishImgCheckbox.label "Include images and other files">
+<!ENTITY publishImgCheckbox.accesskey "o">
+<!ENTITY publishImgCheckbox.tooltip "Publish images and other files referenced by this page">
+<!ENTITY sameLocationRadio.label "Use same location as page">
+<!ENTITY sameLocationRadio.accesskey "U">
+<!ENTITY sameLocationRadio.tooltip "Publish files to the same location as the page">
+<!ENTITY useSubdirRadio.label "Use this site subdirectory:">
+<!ENTITY useSubdirRadio.accesskey "d">
+<!ENTITY useSubdirRadio.tooltip "Publish files to the selected remote subdirectory">
+<!ENTITY otherDirList.tooltip "Choose or enter name of remote subdirectory where files will be published">
+<!ENTITY pageTitle.label "Page Title:">
+<!ENTITY pageTitle.accesskey "T">
+<!ENTITY pageTitle.tooltip "Enter a title to identify the page in the window and in bookmarks">
+<!ENTITY pageTitleExample.label "e.g.: "My Web Page"">
+<!ENTITY filename.label "Filename:">
+<!ENTITY filename.accesskey "F">
+<!ENTITY filename.tooltip "Enter a name for this file, including '.html' for a web page">
+<!ENTITY filenameExample.label "e.g,: "mypage.html"">
+<!ENTITY relatedDocs.label "Other files to publish">
+<!ENTITY setDefaultButton.label "Set as Default">
+<!ENTITY setDefaultButton.accesskey "D">
+<!ENTITY setDefSiteAndDir.label "Set as Default Site and Directory">
+<!ENTITY removeButton.label "Remove Site">
+<!ENTITY removeButton.accesskey "R">
+
+<!-- Settings Tab Panel -->
+<!ENTITY publishSites.label "Publishing Sites">
+<!ENTITY serverInfo.label "Server Information">
+<!ENTITY loginInfo.label "Login Information">
+<!ENTITY siteName.label "Site Name:">
+<!ENTITY siteName.accesskey "e">
+<!ENTITY siteName.tooltip "A nickname that identifies this publishing site (e.g.: 'MySite')">
+<!ENTITY siteUrl.label "Publishing address (e.g.: 'ftp://ftp.myisp.com/myusername'):">
+<!ENTITY siteUrl.accesskey "a">
+<!ENTITY siteUrl.tooltip "The FTP:// or HTTP:// address provided by your ISP or web hosting service">
+<!ENTITY browseUrl.label "HTTP address of your homepage (e.g.: 'http://www.myisp.com/myusername'):">
+<!ENTITY browseUrl.accesskey "T">
+<!ENTITY browseUrl.tooltip "The HTTP:// address of your home directory (don't include filename)">
+<!ENTITY username.label "User name:">
+<!ENTITY username.accesskey "U">
+<!ENTITY username.tooltip "The user name you use to log in to your ISP or web hosting service">
+<!ENTITY password.label "Password:">
+<!ENTITY password.accesskey "w">
+<!ENTITY password.tooltip "The password associated with your user name">
+<!ENTITY savePassword.label "Save Password">
+<!ENTITY savePassword.accesskey "S">
+<!ENTITY savePassword.tooltip "Select this to save your password securely using Password Manager">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorPublishProgress.dtd
@@ -0,0 +1,52 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Charles Manske (cmanske@netscape.com)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY siteUrl.label "Site URL:">
+<!ENTITY docSubdir.label "Page subdirectory:">
+<!ENTITY otherSubdir.label "Image subdirectory:">
+
+<!ENTITY status.label "Publishing…">
+<!ENTITY fileList.label "Publishing Status">
+<!ENTITY statusHeader.label "Status">
+<!ENTITY filenameHeader.label "Filename">
+<!ENTITY succeeded.label "Succeeded">
+<!ENTITY failed.label "Failed">
+
+<!ENTITY keepOpen "Keep this window open after publishing is complete.">
+<!ENTITY closeButton.label "Close">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorReplace.dtd
@@ -0,0 +1,61 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Akkana Peck
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- extracted from EdReplace.xul -->
+
+<!ENTITY replaceDialog.title "Find and Replace">
+<!ENTITY findField.label "Find text:">
+<!ENTITY findField.accesskey "n">
+<!ENTITY replaceField.label "Replace with:">
+<!ENTITY replaceField.accesskey "e">
+<!ENTITY caseSensitiveCheckbox.label "Match exact case">
+<!ENTITY caseSensitiveCheckbox.accesskey "c">
+<!ENTITY wrapCheckbox.label "Wrap around">
+<!ENTITY wrapCheckbox.accesskey "W">
+<!ENTITY backwardsCheckbox.label "Search backwards">
+<!ENTITY backwardsCheckbox.accesskey "b">
+<!ENTITY findNextButton.label "Find Next">
+<!ENTITY findNextButton.accesskey "F">
+<!ENTITY replaceButton.label "Replace">
+<!ENTITY replaceButton.accesskey "R">
+<!ENTITY replaceAndFindButton.label "Replace and Find">
+<!ENTITY replaceAndFindButton.accesskey "d">
+<!ENTITY replaceAllButton.label "Replace All">
+<!ENTITY replaceAllButton.accesskey "A">
+<!ENTITY closeButton.label "Close">
+<!ENTITY notFoundWarning.label "The text you entered was not found.">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorSaveAsCharset.dtd
@@ -0,0 +1,50 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- These strings are generic to all or most of the editor's dialogs. -->
+
+<!-- This button is for the progressive disclosure of additional editing functionality -->
+
+<!-- These strings are for use specifically in the editor's link dialog. -->
+<!ENTITY windowTitle.label "Save And Change Character Encoding">
+<!ENTITY documentTitleTitle.label "Page Title">
+<!ENTITY documentCharsetTitle.label "Character Encoding">
+<!ENTITY documentCharsetDesc.label "Select the character encoding you want to save a document in:">
+<!ENTITY documentExportToText.label "Export to Text">
+
+
+
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorSelectProperties.dtd
@@ -0,0 +1,80 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Input Tag Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Selection List Properties">
+
+<!ENTITY Select.label "Selection List">
+<!ENTITY SelectName.label "List Name:">
+<!ENTITY SelectName.accesskey "N">
+<!ENTITY SelectSize.label "Height:">
+<!ENTITY SelectSize.accesskey "H">
+<!ENTITY SelectMultiple.label "Multiple Selection">
+<!ENTITY SelectMultiple.accesskey "M">
+<!ENTITY SelectDisabled.label "Disabled">
+<!ENTITY SelectDisabled.accesskey "D">
+<!ENTITY SelectTabIndex.label "Tab Index:">
+<!ENTITY SelectTabIndex.accesskey "I">
+
+<!ENTITY OptGroup.label "Option Group">
+<!ENTITY OptGroupLabel.label "Label:">
+<!ENTITY OptGroupLabel.accesskey "L">
+<!ENTITY OptGroupDisabled.label "Disabled">
+<!ENTITY OptGroupDisabled.accesskey "D">
+
+<!ENTITY Option.label "Option">
+<!ENTITY OptionText.label "Text:">
+<!ENTITY OptionText.accesskey "T">
+<!ENTITY OptionValue.label "Value:">
+<!ENTITY OptionValue.accesskey "V">
+<!ENTITY OptionSelected.label "Initially Selected">
+<!ENTITY OptionSelected.accesskey "S">
+<!ENTITY OptionDisabled.label "Disabled">
+<!ENTITY OptionDisabled.accesskey "D">
+
+<!ENTITY TextHeader.label "Text">
+<!ENTITY ValueHeader.label "Value">
+<!ENTITY SelectedHeader.label "Selected">
+
+<!ENTITY AddOption.label "Add Option">
+<!ENTITY AddOption.accesskey "O">
+<!ENTITY AddOptGroup.label "Add Group">
+<!ENTITY AddOptGroup.accesskey "G">
+<!ENTITY RemoveElement.label "Remove">
+<!ENTITY RemoveElement.accesskey "R">
+<!ENTITY MoveElementUp.label "Move Up">
+<!ENTITY MoveElementUp.accesskey "U">
+<!ENTITY MoveElementDown.label "Move Down">
+<!ENTITY MoveElementDown.accesskey "D">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorSnapToGrid.dtd
@@ -0,0 +1,48 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla.org.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Daniel Glazman (glazman@netscape.com) (Original author)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Snap to Grid">
+
+<!ENTITY enableSnapToGrid.label "enable Snap to Grid">
+<!ENTITY enableSnapToGrid.accessKey "e">
+
+<!ENTITY sizeEditField.label "Size:">
+<!ENTITY sizeEditField.accessKey "S">
+
+<!ENTITY pixelsLabel.value "pixels">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorSpellCheck.dtd
@@ -0,0 +1,71 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!-- Window title -->
+<!ENTITY windowTitle.label "Check Spelling">
+
+<!ENTITY misspelledWord.label "Misspelled word:">
+<!ENTITY wordEditField.label "Replace with:">
+<!ENTITY wordEditField.accessKey "w">
+<!ENTITY checkwordButton.label "Check Word">
+<!ENTITY checkwordButton.accessKey "k">
+<!ENTITY suggestions.label "Suggestions:">
+<!ENTITY suggestions.accessKey "u">
+<!ENTITY ignoreButton.label "Ignore">
+<!ENTITY ignoreButton.accessKey "I">
+<!ENTITY ignoreAllButton.label "Ignore All">
+<!ENTITY ignoreAllButton.accessKey "n">
+<!ENTITY replaceButton.label "Replace">
+<!ENTITY replaceButton.accessKey "R">
+<!ENTITY replaceAllButton.label "Replace All">
+<!ENTITY replaceAllButton.accessKey "A">
+<!ENTITY stopButton.label "Stop">
+<!ENTITY stopButton.accessKey "t">
+<!ENTITY userDictionary.label "Personal Dictionary:">
+<!ENTITY moreDictionaries.label "Download more dictionaries…">
+<!ENTITY addToUserDictionaryButton.label "Add Word">
+<!ENTITY addToUserDictionaryButton.accessKey "d">
+<!ENTITY editUserDictionaryButton.label "Edit…">
+<!ENTITY editUserDictionaryButton.accessKey "E">
+<!ENTITY recheckButton.label "Recheck Page">
+<!ENTITY recheckButton.accessKey "P">
+<!ENTITY closeButton.label "Close">
+<!ENTITY closeButton.accessKey "C">
+<!ENTITY sendButton.label "Send">
+<!ENTITY sendButton.accessKey "S">
+<!ENTITY languagePopup.label "Language:">
+<!ENTITY languagePopup.accessKey "L">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorTableProperties.dtd
@@ -0,0 +1,116 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY tableWindow.title "Table Properties">
+<!ENTITY applyButton.label "Apply">
+<!ENTITY applyButton.accesskey "A">
+<!ENTITY closeButton.label "Close">
+<!ENTITY tableTab.label "Table">
+<!ENTITY cellTab.label "Cells">
+<!ENTITY tableRows.label "Rows:">
+<!ENTITY tableRows.accessKey "R">
+<!ENTITY tableColumns.label "Columns:">
+<!ENTITY tableColumns.accessKey "C">
+<!ENTITY tableHeight.label "Height:">
+<!ENTITY tableHeight.accessKey "G">
+<!ENTITY tableWidth.label "Width:">
+<!ENTITY tableWidth.accessKey "W">
+<!ENTITY tableBorderSpacing.label "Borders and Spacing">
+<!ENTITY tableBorderWidth.label "Border:">
+<!ENTITY tableBorderWidth.accessKey "B">
+<!ENTITY tableSpacing.label "Spacing:">
+<!ENTITY tableSpacing.accessKey "S">
+<!ENTITY tablePadding.label "Padding:">
+<!ENTITY tablePadding.accessKey "P">
+<!ENTITY tablePxBetwCells.label "pixels between cells">
+<!ENTITY tablePxBetwBrdrCellContent.label "pixels between cell border and content">
+<!ENTITY tableAlignment.label "Table Alignment:">
+<!ENTITY tableAlignment.accessKey "T">
+<!ENTITY tableCaption.label "Caption:">
+<!ENTITY tableCaption.accessKey "N">
+<!ENTITY tableCaptionAbove.label "Above Table">
+<!ENTITY tableCaptionBelow.label "Below Table">
+<!ENTITY tableCaptionLeft.label "Left of Table">
+<!ENTITY tableCaptionRight.label "Right of table">
+<!ENTITY tableCaptionNone.label "None">
+<!ENTITY tableInheritColor.label "(Let page color show through)">
+
+<!ENTITY cellPercent.label "percent of table">
+<!ENTITY cellSelection.label "Selection">
+<!ENTITY cellSelectCell.label "Cell">
+<!ENTITY cellSelectRow.label "Row">
+<!ENTITY cellSelectColumn.label "Column">
+<!ENTITY cellSelectNext.label "Next">
+<!ENTITY cellSelectNext.accessKey "N">
+<!ENTITY cellSelectPrevious.label "Previous">
+<!ENTITY cellSelectPrevious.accessKey "P">
+<!ENTITY cellApplyBeforeMove.label "Apply changes before changing selection">
+<!ENTITY cellKeepCurrentData.label "Keep current settings">
+<!-- LOCALIZATION NOTE Next 2 form 1 sentence (we don't want to use HTML tag to wrap) -->
+<!ENTITY applyBeforeChange1.label "Current changes will be applied">
+<!ENTITY applyBeforeChange2.label "before changing the selection.">
+<!ENTITY cellRowSpan.label "Row Span:">
+<!ENTITY cellColSpan.label "Column Span:">
+<!ENTITY cellContentAlignment.label "Content Alignment">
+<!ENTITY cellHorizontal.label "Horizontal:">
+<!ENTITY cellHorizontal.accessKey "Z">
+<!ENTITY cellVertical.label "Vertical:">
+<!ENTITY cellVertical.accessKey "V">
+<!ENTITY cellStyle.label "Cell Style:">
+<!ENTITY cellStyle.accessKey "C">
+<!ENTITY cellNormal.label "Normal">
+<!ENTITY cellHeader.label "Header">
+<!ENTITY cellTextWrap.label "Text Wrap:">
+<!ENTITY cellTextWrap.accessKey "T">
+<!ENTITY cellWrap.label "Wrap">
+<!ENTITY cellNoWrap.label "Don't wrap">
+<!ENTITY cellAlignTop.label "Top">
+<!ENTITY cellAlignMiddle.label "Middle">
+<!ENTITY cellAlignBottom.label "Bottom">
+<!ENTITY cellAlignJustify.label "Justify">
+<!ENTITY cellAlignAtChar.label "At Character:">
+<!ENTITY cellInheritColor.label "(Let table color show through)">
+<!ENTITY cellUseCheckboxHelp.label "Use checkboxes to determine which properties are applied to all selected cells">
+
+<!-- Used in both Table and Cell panels -->
+<!ENTITY size.label "Size">
+<!ENTITY pixels.label "pixels">
+<!ENTITY backgroundColor.label "Background Color:">
+<!ENTITY backgroundColor.accessKey "B">
+<!ENTITY AlignLeft.label "Left">
+<!ENTITY AlignCenter.label "Center">
+<!ENTITY AlignRight.label "Right">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/dialogs/EditorTextAreaProperties.dtd
@@ -0,0 +1,65 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Text Area Properties Dialog.
+ -
+ - The Initial Developer of the Original Code is
+ - Neil Rashbrook.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<!ENTITY windowTitle.label "Text Area Properties">
+
+<!ENTITY Settings.label "Settings">
+
+<!ENTITY TextAreaName.label "Field Name:">
+<!ENTITY TextAreaName.accessKey "N">
+<!ENTITY TextAreaRows.label "Rows:">
+<!ENTITY TextAreaRows.accessKey "R">
+<!ENTITY TextAreaCols.label "Columns:">
+<!ENTITY TextAreaCols.accessKey "C">
+<!ENTITY TextAreaReadOnly.label "Read Only">
+<!ENTITY TextAreaReadOnly.accessKey "O">
+<!ENTITY TextAreaDisabled.label "Disabled">
+<!ENTITY TextAreaDisabled.accessKey "D">
+<!ENTITY TextAreaTabIndex.label "Tab Index:">
+<!ENTITY TextAreaTabIndex.accessKey "I">
+<!ENTITY TextAreaAccessKey.label "Access Key:">
+<!ENTITY TextAreaAccessKey.accessKey "K">
+<!ENTITY InitialText.label "Initial Text:">
+<!ENTITY InitialText.accessKey "T">
+
+<!ENTITY TextAreaWrap.label "Wrap Mode:">
+<!ENTITY TextAreaWrap.accessKey "W">
+<!ENTITY WrapDefault.value "Default">
+<!ENTITY WrapOff.value "Off">
+<!ENTITY WrapHard.value "Hard">
+<!ENTITY WrapSoft.value "Soft">
+<!ENTITY WrapPhysical.value "Physical">
+<!ENTITY WrapVirtual.value "Virtual">
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/en-US/chrome/region/region.properties
@@ -0,0 +1,4 @@
+#
+# editor.js
+# editor.properties
+editor.throbber.url=http://www.seamonkey-project.org/
new file mode 100644
--- /dev/null
+++ b/editor/ui/locales/jar.mn
@@ -0,0 +1,54 @@
+#filter substitution
+
+@AB_CD@.jar:
+% locale editor @AB_CD@ %locale/@AB_CD@/editor/
+ locale/@AB_CD@/editor/editorSmileyOverlay.dtd (%chrome/composer/editorSmileyOverlay.dtd)
+ locale/@AB_CD@/editor/editorOverlay.dtd (%chrome/composer/editorOverlay.dtd)
+ locale/@AB_CD@/editor/editor.properties (%chrome/composer/editor.properties)
+ locale/@AB_CD@/editor/EditorHLineProperties.dtd (%chrome/dialogs/EditorHLineProperties.dtd)
+ locale/@AB_CD@/editor/EditorImageProperties.dtd (%chrome/dialogs/EditorImageProperties.dtd)
+ locale/@AB_CD@/editor/EditorInsertSource.dtd (%chrome/dialogs/EditorInsertSource.dtd)
+ locale/@AB_CD@/editor/EditorInsertChars.dtd (%chrome/dialogs/EditorInsertChars.dtd)
+ locale/@AB_CD@/editor/EditorInsertTable.dtd (%chrome/dialogs/EditorInsertTable.dtd)
+ locale/@AB_CD@/editor/EditorInsertTOC.dtd (%chrome/dialogs/EditorInsertTOC.dtd)
+ locale/@AB_CD@/editor/EditorLinkProperties.dtd (%chrome/dialogs/EditorLinkProperties.dtd)
+ locale/@AB_CD@/editor/EditorListProperties.dtd (%chrome/dialogs/EditorListProperties.dtd)
+ locale/@AB_CD@/editor/EditorColorProperties.dtd (%chrome/dialogs/EditorColorProperties.dtd)
+ locale/@AB_CD@/editor/EdColorPicker.dtd (%chrome/dialogs/EdColorPicker.dtd)
+ locale/@AB_CD@/editor/EditorReplace.dtd (%chrome/dialogs/EditorReplace.dtd)
+ locale/@AB_CD@/editor/EditorSpellCheck.dtd (%chrome/dialogs/EditorSpellCheck.dtd)
+ locale/@AB_CD@/editor/EditorPersonalDictionary.dtd (%chrome/dialogs/EditorPersonalDictionary.dtd)
+ locale/@AB_CD@/editor/EditorTableProperties.dtd (%chrome/dialogs/EditorTableProperties.dtd)
+ locale/@AB_CD@/editor/EditorFormProperties.dtd (%chrome/dialogs/EditorFormProperties.dtd)
+ locale/@AB_CD@/editor/EditorInputProperties.dtd (%chrome/dialogs/EditorInputProperties.dtd)
+ locale/@AB_CD@/editor/EditorTextAreaProperties.dtd (%chrome/dialogs/EditorTextAreaProperties.dtd)
+ locale/@AB_CD@/editor/EditorSelectProperties.dtd (%chrome/dialogs/EditorSelectProperties.dtd)
+ locale/@AB_CD@/editor/EditorButtonProperties.dtd (%chrome/dialogs/EditorButtonProperties.dtd)
+ locale/@AB_CD@/editor/EditorLabelProperties.dtd (%chrome/dialogs/EditorLabelProperties.dtd)
+ locale/@AB_CD@/editor/EditorFieldSetProperties.dtd (%chrome/dialogs/EditorFieldSetProperties.dtd)
+ locale/@AB_CD@/editor/EdNamedAnchorProperties.dtd (%chrome/dialogs/EdNamedAnchorProperties.dtd)
+ locale/@AB_CD@/editor/EdDialogOverlay.dtd (%chrome/dialogs/EdDialogOverlay.dtd)
+ locale/@AB_CD@/editor/EdAdvancedEdit.dtd (%chrome/dialogs/EdAdvancedEdit.dtd)
+ locale/@AB_CD@/editor/EdConvertToTable.dtd (%chrome/dialogs/EdConvertToTable.dtd)
+
+
+#ifdef MOZ_SUITE
+@AB_CD@.jar:
+% locale editor-region @AB_CD@ %locale/@AB_CD@/editor-region/
+ locale/@AB_CD@/editor/editor.dtd (%chrome/composer/editor.dtd)
+ locale/@AB_CD@/editor/editorPrefsOverlay.dtd (%chrome/composer/editorPrefsOverlay.dtd)
+ locale/@AB_CD@/editor/editorNavigatorOverlay.dtd (%chrome/composer/editorNavigatorOverlay.dtd)
+ locale/@AB_CD@/editor/pref-toolbars.dtd (%chrome/composer/pref-toolbars.dtd)
+ locale/@AB_CD@/editor/pref-editing.dtd (%chrome/composer/pref-editing.dtd)
+ locale/@AB_CD@/editor/pref-composer.dtd (%chrome/composer/pref-composer.dtd)
+ locale/@AB_CD@/editor/EdLinkChecker.dtd (%chrome/dialogs/EdLinkChecker.dtd)
+ locale/@AB_CD@/editor/EditorPageProperties.dtd (%chrome/dialogs/EditorPageProperties.dtd)
+ locale/@AB_CD@/editor/EditorSnapToGrid.dtd (%chrome/dialogs/EditorSnapToGrid.dtd)
+ locale/@AB_CD@/editor/EditorImageMap.dtd (%chrome/dialogs/EditorImageMap.dtd)
+ locale/@AB_CD@/editor/EditorImageMapHotSpot.dtd (%chrome/dialogs/EditorImageMapHotSpot.dtd)
+ locale/@AB_CD@/editor/EditConflict.dtd (%chrome/dialogs/EditConflict.dtd)
+ locale/@AB_CD@/editor/EditorSaveAsCharset.dtd (%chrome/dialogs/EditorSaveAsCharset.dtd)
+ locale/@AB_CD@/editor/EditorPublish.dtd (%chrome/dialogs/EditorPublish.dtd)
+ locale/@AB_CD@/editor/EditorPublishProgress.dtd (%chrome/dialogs/EditorPublishProgress.dtd)
+ locale/@AB_CD@/editor-region/region.properties (%chrome/region/region.properties)
+#endif
new file mode 100644
--- /dev/null
+++ b/editor/ui/makefiles.sh
@@ -0,0 +1,42 @@
+#! /bin/sh
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the the Mozilla build system
+#
+# The Initial Developer of the Original Code is
+# Ben Turner <mozilla@songbirdnest.com>
+#
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+add_makefiles "
+editor/ui/Makefile
+editor/ui/locales/Makefile
+"
new file mode 100644
--- /dev/null
+++ b/editor/ui/nsComposerCmdLineHandler.js
@@ -0,0 +1,215 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Seamonkey Composer.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg <bsmedberg@covad.net>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const nsICmdLineHandler = Components.interfaces.nsICmdLineHandler;
+const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
+const nsIFactory = Components.interfaces.nsIFactory;
+const nsISupports = Components.interfaces.nsISupports;
+const nsIModule = Components.interfaces.nsIModule;
+const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
+const nsICategoryManager = Components.interfaces.nsICategoryManager;
+const nsISupportsString = Components.interfaces.nsISupportsString;
+const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
+
+const NS_ERROR_FAILURE = Components.results.NS_ERROR_FAILURE;
+const NS_ERROR_NO_AGGREGATION = Components.results.NS_ERROR_NO_AGGREGATION;
+const NS_ERROR_NO_INTERFACE = Components.results.NS_ERROR_NO_INTERFACE;
+
+function nsComposerCmdLineHandler() {}
+nsComposerCmdLineHandler.prototype = {
+ get wrappedJSObject() {
+ return this;
+ },
+
+ /* nsISupports */
+
+ QueryInterface: function(iid) {
+ if (iid.equals(nsISupports))
+ return this;
+
+ if (nsICmdLineHandler && iid.equals(nsICmdLineHandler))
+ return this;
+
+ if (nsICommandLineHandler && iid.equals(nsICommandLineHandler))
+ return this;
+
+ throw NS_ERROR_NO_INTERFACE;
+ },
+
+ /* nsICmdLineHandler */
+ commandLineArgument : "-edit",
+ prefNameForStartup : "general.startup.editor",
+ chromeUrlForTask : "chrome://editor/content/editor.xul",
+ helpText : "Start with editor.",
+ handlesArgs : true,
+ defaultArgs : "about:blank",
+ openWindowWithArgs : true,
+
+ /* nsICommandLineHandler */
+ handle : function handle(cmdLine) {
+ var args = Components.classes["@mozilla.org/supports-string;1"]
+ .createInstance(nsISupportsString);
+ try {
+ var uristr = cmdLine.handleFlagWithParam("edit", false);
+ if (uristr == null) {
+ // Try the editor flag (used for general.startup.* prefs)
+ uristr = cmdLine.handleFlagWithParam("editor", false);
+ if (uristr == null)
+ return;
+ }
+
+ try {
+ args.data = cmdLine.resolveURI(uristr).spec;
+ }
+ catch (e) {
+ return;
+ }
+ }
+ catch (e) {
+ // One of the flags is present but no data, so set default arg.
+ args.data = "about:blank";
+ }
+
+ var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(nsIWindowWatcher);
+ wwatch.openWindow(null, "chrome://editor/content", "_blank",
+ "chrome,dialog=no,all", args);
+ cmdLine.preventDefault = true;
+ },
+
+ helpInfo : " -edit <url> Open Composer.\n"
+};
+
+function nsComposerCmdLineHandlerFactory() {
+}
+
+nsComposerCmdLineHandlerFactory.prototype = {
+ /* nsISupports */
+
+ QueryInterface: function(iid) {
+ if (!iid.equals(nsIFactory) &&
+ !iid.equals(nsISupports)) {
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+ return this;
+ },
+
+ /* nsIFactory */
+ createInstance: function(outer, iid) {
+ if (outer != null) {
+ throw NS_ERROR_NO_AGGREGATION;
+ }
+
+ return new nsComposerCmdLineHandler().QueryInterface(iid);
+ },
+
+ lockFactory: function(lock) {
+ }
+};
+
+const nsComposerCmdLineHandler_CID =
+ Components.ID("{f7d8db95-ab5d-4393-a796-9112fe758cfa}");
+
+const ContractIDPrefix =
+ "@mozilla.org/commandlinehandler/general-startup;1?type=";
+
+var thisModule = {
+ /* nsISupports */
+
+ QueryInterface: function(iid) {
+ if (!iid.equals(nsIModule) &&
+ !iid.equals(nsISupports)) {
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+ return this;
+ },
+
+ /* nsIModule */
+
+ getClassObject: function (compMgr, cid, iid) {
+ if (!cid.equals(nsComposerCmdLineHandler_CID)) {
+ throw NS_ERROR_FAILURE;
+ }
+
+ if (!iid.equals(nsIFactory)) {
+ throw NS_ERROR_NO_INTERFACE;
+ }
+
+ return new nsComposerCmdLineHandlerFactory();
+ },
+
+ registerSelf: function (compMgr, fileSpec, location, type) {
+ var compReg = compMgr.QueryInterface(nsIComponentRegistrar);
+ compReg.registerFactoryLocation(nsComposerCmdLineHandler_CID,
+ "nsComposerCmdLineHandler",
+ ContractIDPrefix + "edit",
+ fileSpec, location, type);
+ compReg.registerFactoryLocation(nsComposerCmdLineHandler_CID,
+ "nsComposerCmdLineHandler",
+ ContractIDPrefix + "editor",
+ fileSpec, location, type);
+
+ var catMan = Components.classes["@mozilla.org/categorymanager;1"].getService(nsICategoryManager);
+ catMan.addCategoryEntry("command-line-argument-handlers",
+ "nsComposerCmdLineHandler",
+ ContractIDPrefix + "edit",
+ true, true);
+ catMan.addCategoryEntry("command-line-handler",
+ "m-edit",
+ ContractIDPrefix + "edit",
+ true, true);
+ },
+
+ unregisterSelf: function (compMgr, location, type) {
+ var compReg = compMgr.QueryInterface(nsIComponentRegistrar);
+ compReg.unregisterFactoryLocation(nsComposerCmdLineHandler_CID,
+ location);
+
+ var catMan = Components.classes["@mozilla.org/categorymanager;1"].getService(nsICategoryManager);
+ catMan.deleteCategoryEntry("command-line-argument-handlers",
+ "nsComposerCmdLineHandler", true);
+ catMan.deleteCategoryEntry("command-line-handler",
+ "m-edit", true);
+ },
+
+ canUnload: function (compMgr) {
+ return true;
+ }
+};
+
+function NSGetModule(compMgr, fileSpec) {
+ return thisModule;
+}
--- a/mail/build.mk
+++ b/mail/build.mk
@@ -38,31 +38,33 @@
ifndef COMM_BUILD # Mozilla Makefile
ifndef LIBXUL_SDK
include $(topsrcdir)/toolkit/toolkit-tiers.mk
endif
TIERS += app
-tier_app_dirs += editor/ui
-
ifdef MOZ_EXTENSIONS
tier_app_dirs += extensions
endif
else # toplevel Makefile
TIERS += app
ifdef MOZ_LDAP_XPCOM
tier_app_staticdirs += directory/c-sdk
tier_app_dirs += directory/xpcom
endif
+ifdef MOZ_COMPOSER
+tier_app_dirs += editor/ui
+endif
+
ifdef MOZ_BRANDING_DIRECTORY
tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
else
tier_app_dirs += mail/branding/nightly
endif
tier_app_dirs += \
mailnews \
--- a/mail/locales/Makefile.in
+++ b/mail/locales/Makefile.in
@@ -106,17 +106,17 @@ ISP_FILES = $(shell cat $(LOCALE_SRCDIR)
libs:: $(addsuffix .rdf,$(ISP_FILES))
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/isp/$(AB_CD)
install:: $(addsuffix .rdf,$(ISP_FILES))
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/isp/$(AB_CD)
libs-%:
@$(MAKE) -C ../../mozilla/toolkit/locales libs-$*
- @$(MAKE) -C ../../mozilla/editor/ui/locales AB_CD=$* XPI_NAME=locale-$*
+ @$(MAKE) -C ../../editor/ui/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../../mozilla/extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=defaults/pref
ifdef MOZ_BRANDING_DIRECTORY
@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$*
else
@$(MAKE) -C $(DEPTH)/mail/branding/nightly/locales AB_CD=$* XPI_NAME=locale-$*
endif
--- a/suite/build.mk
+++ b/suite/build.mk
@@ -38,33 +38,33 @@
ifndef COMM_BUILD # Mozilla Makefile
ifndef LIBXUL_SDK
include $(topsrcdir)/toolkit/toolkit-tiers.mk
endif
TIERS += app
-ifdef MOZ_COMPOSER
-tier_app_dirs += editor/ui
-endif
-
ifdef MOZ_EXTENSIONS
tier_app_dirs += extensions
endif
else # toplevel Makefile
TIERS += app
ifdef MOZ_LDAP_XPCOM
tier_app_staticdirs += directory/c-sdk
tier_app_dirs += directory/xpcom
endif
+ifdef MOZ_COMPOSER
+tier_app_dirs += editor/ui
+endif
+
ifdef MOZ_BRANDING_DIRECTORY
tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
endif
ifdef MOZ_MAIL_NEWS
tier_app_dirs += mailnews
endif
--- a/suite/locales/Makefile.in
+++ b/suite/locales/Makefile.in
@@ -133,17 +133,17 @@ SEARCH_PLUGINS := $(shell cat $(LOCALE_S
libs:: $(addsuffix .src,$(SEARCH_PLUGINS)) $(addsuffix .png,$(SEARCH_PLUGINS))
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/searchplugins
install:: $(addsuffix .src,$(SEARCH_PLUGINS)) $(addsuffix .png,$(SEARCH_PLUGINS))
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/searchplugins
libs-%:
@$(MAKE) -C ../../mozilla/toolkit/locales libs-$*
- @$(MAKE) -C ../../mozilla/editor/ui/locales AB_CD=$* XPI_NAME=locale-$*
+ @$(MAKE) -C ../../editor/ui/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../../mozilla/extensions/irc/locales libs-$*
@$(MAKE) -C ../../mozilla/extensions/venkman/locales libs-$*
@$(MAKE) -C ../../mozilla/extensions/reporter/locales libs AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../../mozilla/extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=defaults/pref
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
MOZ_PKG_MAC_DSSTORE=$(_ABS_DIST)/branding/dsstore